Pertanyaan Bisakah saya membuat tampilan dengan parameter di MySQL?


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;

Tapi mysql tidak mengizinkan ini.

Saya menemukan solusi yang buruk:

CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|

Dan kemudian lihat adalah:

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = GetMyVariable();

Tapi kelihatannya benar-benar jelek, dan penggunaannya juga jelek - saya harus mengatur @MyVariable sebelum setiap penggunaan tampilan.

Apakah ada solusi, yang bisa saya gunakan seperti ini:

SELECT Column FROM MyView(2) WHERE (...)

Situasi konkret adalah sebagai berikut: Saya memiliki tabel yang menyimpan informasi tentang permintaan 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 jumlah permintaan identik yang direkam dalam detik yang sama. Saya ingin menampilkan daftar penolakan, tetapi kadang-kadang, ketika aplikasi ditolak, itu mencoba beberapa kali hanya untuk memastikan. Jadi biasanya, ketika pengguna yang sama mendapatkan penolakan 3 kali pada fitur yang sama dalam beberapa detik, itu sebenarnya adalah satu penyangkalan. 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 timestamp: 1,2,24,26,27,45 dan pengguna ingin kelompok penyangkalan yang lebih dekat satu sama lain dari 4 detik, dia harus mendapatkan sesuatu seperti ini: 1 (x2), 24 (x3), 45 (x1). Kita dapat mengasumsikan, bahwa ruang antara penolakan nyata jauh lebih besar daripada di antara duplikasi. Saya memecahkan masalah dengan cara berikut:

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 menunjukkan penolakan dari pengguna 1 dan 2 pada fitur 3 dan 4 digabung 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 tampilan, karena di dalamnya sangat mudah untuk memfilter data dan menggunakannya secara eksplisit dalam kisi jQuery, secara otomatis memesan, membatasi jumlah rekaman, dan sebagainya.

Tapi itu hanya solusi yang jelek. Apakah ada cara yang tepat untuk melakukan ini?


76
2018-02-17 15:25


asal


Jawaban:


Sebenarnya jika Anda membuat func:

create function p1() returns INTEGER DETERMINISTIC NO SQL return @p1;

dan lihat:

create view h_parm as
select * from sw_hardware_big where unit_id = p1() ;

Kemudian Anda dapat memanggil tampilan dengan parameter:

select s.* from (select @p1:=12 p) parm , h_parm s;

Saya harap itu membantu.


121
2018-03-16 21:09



CREATE VIEW MyView AS
   SELECT Column, Value FROM Table;


SELECT Column FROM MyView WHERE Value = 1;

Apakah solusi yang tepat di MySQL, beberapa SQL lainnya memungkinkan Anda menentukan Tampilan lebih tepat.

Catatan: Kecuali View sangat rumit, MySQL akan mengoptimalkan ini dengan baik.


18
2018-02-17 15:47



Saya sebelumnya datang dengan solusi yang berbeda yang tidak menggunakan prosedur yang tersimpan, melainkan menggunakan tabel parameter dan beberapa connection_id () magic.

EDIT (Disalin dari komentar)

buat tabel yang berisi kolom yang disebut connection_id (buatlah bigint). Tempatkan kolom di tabel itu untuk parameter untuk tampilan. Taruh kunci utama pada connection_id. ganti ke tabel parameter dan gunakan CONNECTION_ID() untuk mengisi nilai connection_id. Dalam tampilan, gunakan gabungan gabungan ke tabel parameter dan letakkan WHERE param_table.connection_id = CONNECTION_ID(). Ini akan menyeberang bergabung dengan hanya satu baris dari tabel parameter yang adalah apa yang Anda inginkan. Anda kemudian dapat menggunakan kolom lain di mana klausa misalnya di mana orders.order_id = param_table.order_id.


1
2018-04-06 17:20