1. ホーム
  2. mysql

[解決済み] MySQLでパラメータ付きのビューを作成できますか?

2022-12-17 01:08:08

質問

このようなビューがあります。

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = 2;

もっと汎用的にしたいのは、2を変数に変えるということです。これを試してみました。

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = @MyVariable;

しかし、MySQLはこれを許さない。

私は醜い回避策を見つけました。

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

そして、ビューは

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

しかし、これは本当にくだらなく見えますし、使い方もくだらなく、ビューを使う前に毎回@MyVariableを設定しなければなりません。

このように使うことができる、解決策はありますか。

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

具体的には以下のような状況です。 拒否されたリクエストに関する情報を格納するテーブルを持っています。

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;

多重度とは、同じ秒数の間に記録された同一のリクエストの数のことです。拒否のリストを表示したいのですが、アプリケーションが拒否されると、念のため2回ほど再試行することがあります。そのため、通常、同じユーザーが数秒間に同じ機能で3回拒否された場合、実際には1回の拒否になります。もし、このリクエストを満たすために、もう1つリソースがあれば、次の2回の拒否は起こりません。そこで、拒否をグループ化し、ユーザが拒否をグループ化する時間帯を指定できるようにしたいと思います。例えば、タイムスタンプ1,2,24,26,27,45で拒否があり、ユーザーが4秒より近い拒否をグループ化したい場合、以下のようなものが得られるはずです。1 (x2), 24 (x3), 45 (x1). 実際の拒否の間のスペースは、重複の間のスペースよりはるかに大きいと仮定できます。私は以下の方法でこの問題を解決しました。

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;

そして、5秒ごとにマージされた機能3と4について、ユーザー1と2からの拒否を表示するには、次のようにすればよいでしょう。

SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);

ビューを使うのは、データをフィルタリングしたり、jQueryのグリッドで明示的に使用したり、自動的に順序を変えたり、レコード数を制限したりすることが簡単だからです。

しかし、それはただの醜い回避策です。これを行うための適切な方法はありますか?

どのように解決するのですか?

実は、Func:

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

と表示します。

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

次に、パラメータを指定してビューを呼び出すことができます。

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

お役に立てれば幸いです。