Saya memiliki pandangan seperti ini:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
Saya ingin membuatnya lebih umum, artinya mengubah 2 menjadi variabel. Saya mencoba ini:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
Tetapi MySQL tidak mengizinkan ini.
Saya menemukan solusi yang jelek:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
Dan pandangannya adalah:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
Tapi kelihatannya sangat jelek, dan penggunaannya juga jelek - Saya harus menyetel @MyVariable sebelum setiap penggunaan tampilan.
Apakah ada solusi, yang bisa saya gunakan seperti ini:
SELECT Column FROM MyView(2) WHERE (...)
Situasi konkretnya adalah sebagai berikut: Saya memiliki tabel yang menyimpan informasi tentang permintaan yang ditolak:
CREATE TABLE Denial
(
Id INTEGER UNSIGNED AUTO_INCREMENT,
PRIMARY KEY(Id),
DateTime DATETIME NOT NULL,
FeatureId MEDIUMINT UNSIGNED NOT NULL,
FOREIGN KEY (FeatureId)
REFERENCES Feature (Id)
ON UPDATE CASCADE ON DELETE RESTRICT,
UserHostId MEDIUMINT UNSIGNED NOT NULL,
FOREIGN KEY (UserHostId)
REFERENCES UserHost (Id)
ON UPDATE CASCADE ON DELETE RESTRICT,
Multiplicity MEDIUMINT UNSIGNED NOT NULL DEFAULT 1,
UNIQUE INDEX DenialIndex (FeatureId, DateTime, UserHostId)
) ENGINE = InnoDB;
Multiplisitas adalah sejumlah permintaan identik yang direkam dalam detik yang sama. Saya ingin menampilkan daftar penolakan, tetapi terkadang, ketika aplikasi ditolak, ia mencoba lagi beberapa kali hanya untuk memastikan. Jadi biasanya, ketika pengguna yang sama mendapat penolakan 3 kali pada fitur yang sama dalam beberapa detik, itu sebenarnya adalah satu penolakan. Jika kita memiliki satu sumber daya lagi, untuk memenuhi permintaan ini, dua penolakan berikutnya tidak akan terjadi. Jadi kami ingin mengelompokkan penolakan dalam laporan yang memungkinkan pengguna untuk menentukan rentang waktu di mana penolakan harus dikelompokkan. Misalnya jika kita memiliki penolakan (untuk pengguna 1 pada fitur 1) di cap waktu: 1,2,24,26,27,45 dan pengguna ingin mengelompokkan penolakan yang lebih dekat satu sama lain dari 4 detik, dia harus mendapatkan sesuatu seperti ini: 1 (x2), 24 (x3), 45 (x1). Kita dapat berasumsi, bahwa ruang antara penyangkalan nyata jauh lebih besar daripada di antara duplikasi.
CREATE FUNCTION GetDenialMergingTime()
RETURNS INTEGER UNSIGNED
DETERMINISTIC NO SQL
BEGIN
IF ISNULL(@DenialMergingTime) THEN
RETURN 0;
ELSE
RETURN @DenialMergingTime;
END IF;
END|
CREATE VIEW MergedDenialsViewHelper AS
SELECT MIN(Second.DateTime) AS GroupTime,
First.FeatureId,
First.UserHostId,
SUM(Second.Multiplicity) AS MultiplicitySum
FROM Denial AS First
JOIN Denial AS Second
ON First.FeatureId = Second.FeatureId
AND First.UserHostId = Second.UserHostId
AND First.DateTime >= Second.DateTime
AND First.DateTime - Second.DateTime < GetDenialMergingTime()
GROUP BY First.DateTime, First.FeatureId, First.UserHostId, First.Licenses;
CREATE VIEW MergedDenials AS
SELECT GroupTime,
FeatureId,
UserHostId,
MAX(MultiplicitySum) AS MultiplicitySum
FROM MergedDenialsViewHelper
GROUP BY GroupTime, FeatureId, UserHostId;
Kemudian untuk menampilkan penolakan dari pengguna 1 dan 2 pada fitur 3 dan 4 yang digabungkan setiap 5 detik, yang harus Anda lakukan adalah:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
Saya menggunakan view karena di dalamnya mudah untuk memfilter data dan menggunakannya secara eksplisit di grid jQuery, otomatis memesan, membatasi jumlah record, dan sebagainya.
Tapi itu hanya solusi yang buruk. Apakah ada cara yang tepat untuk melakukan ini?
sumber
CREATE VIEW MyView AS SELECT Column, Value FROM Table; SELECT Column FROM MyView WHERE Value = 1;
Merupakan solusi yang tepat di MySQL, beberapa SQL lain memungkinkan Anda mendefinisikan Tampilan dengan lebih tepat.
Catatan: Kecuali jika Tampilannya sangat rumit, MySQL akan mengoptimalkannya dengan baik.
sumber
Saya sebelumnya menemukan solusi berbeda yang tidak menggunakan prosedur tersimpan, tetapi menggunakan tabel parameter dan beberapa sihir connection_id ().
EDIT (Disalin dari komentar)
buat tabel yang berisi kolom bernama
connection_id
(buatlah menjadi bigint). Tempatkan kolom di tabel itu untuk parameter tampilan. Letakkan kunci utama diconnection_id
. ganti ke dalam tabel parameter dan gunakanCONNECTION_ID()
untuk mengisi nilai connection_id. Dalam tampilan, gunakan gabungan silang ke tabel parameter dan putWHERE param_table.connection_id = CONNECTION_ID()
. Ini akan menggabungkan silang dengan hanya satu baris dari tabel parameter yang Anda inginkan. Anda kemudian dapat menggunakan kolom lain di klausa where misalnya whereorders.order_id = param_table.order_id
.sumber