Могу ли я создать представление с параметром в MySQL?

У меня есть вид вот так:

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;

Множественность - это количество идентичных запросов, записанных за ту же секунду. Я хочу отобразить список опровержений, но иногда, когда приложение получает отказ, он повторяет пару раз, чтобы убедиться. Таким образом, обычно, когда один и тот же пользователь получает отказ в 3 раза за одну и ту же функцию за пару секунд, это фактически один отказ. Если у нас будет еще один ресурс, чтобы выполнить этот запрос, следующих двух опровержений не произойдет. Поэтому мы хотим группировать отрицания в отчете, позволяя пользователю указывать промежуток времени, в котором должны быть сгруппированы отказы. Например. если у нас есть отрицания (для пользователя 1 по функции 1) в отметках времени: 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;

Затем, чтобы показать отказ от пользователей 1 и 2 по функциям 3 и 4, слияние каждые 5 секунд, вам нужно всего лишь:

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

Я использую view, потому что в нем легко фильтровать данные и использовать их в явном виде в сетке jQuery, автоматически заказывать, ограничивать количество записей и т.д.

Но это просто уродливое обходное решение. Есть ли способ сделать это?

Ответ 1

Собственно, если вы создаете 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;

Надеюсь, это поможет.

Ответ 2

CREATE VIEW MyView AS
   SELECT Column, Value FROM Table;


SELECT Column FROM MyView WHERE Value = 1;

Является ли правильное решение в MySQL, некоторые другие SQL позволяют более точно определять представления.

Примечание. Если просмотр слишком сложный, MySQL будет оптимизировать это просто отлично.

Ответ 3

Я ранее придумал другое обходное решение, которое не использует хранимые процедуры, но вместо этого использует таблицу параметров и некоторую магию connection_id().

EDIT (скопировано из комментариев)

создайте таблицу, содержащую столбец с именем connection_id (сделайте его bigint). Поместите столбцы в эту таблицу для параметров для представления. Поместите первичный ключ на connection_id. замените в таблицу параметров и используйте CONNECTION_ID() для заполнения значения connection_id. В представлении используйте кросс-соединение в таблице параметров и поместите WHERE param_table.connection_id = CONNECTION_ID(). Это приведет к перекрестному объединению только с одной строкой из таблицы параметров, которая вам нужна. Затем вы можете использовать другие столбцы в предложении where, где orders.order_id = param_table.order_id.