У мене такий вигляд:
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);
Я використовую подання, оскільки в ньому легко фільтрувати дані та явно використовувати їх у сітці jQuery, автоматично впорядковувати, обмежувати кількість записів тощо.
Але це просто потворне обхідне рішення. Чи є правильний спосіб зробити це?