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