Mam taki widok:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
Chciałbym uczynić go bardziej ogólnym, to znaczy zmienić 2 na zmienną. Próbowałem tego:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
Ale MySQL na to nie pozwala.
Znalazłem brzydkie obejście:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
A potem widok jest:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
Ale wygląda to naprawdę kiepsko, a użycie jest również kiepskie - muszę ustawić @MyVariable przed każdym użyciem widoku.
Czy jest jakieś rozwiązanie, którego mógłbym użyć w ten sposób:
SELECT Column FROM MyView(2) WHERE (...)
Konkretna sytuacja jest następująca: Mam tabelę przechowującą informacje o odrzuconym wniosku:
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;
Wielokrotność to liczba identycznych żądań zarejestrowanych w tej samej sekundzie. Chcę wyświetlić listę odmów, ale czasami, gdy aplikacja zostanie odrzucona, ponawia kilka prób, aby się upewnić. Więc zazwyczaj, gdy ten sam użytkownik otrzymuje odmowę 3 razy tej samej funkcji w ciągu kilku sekund, jest to w rzeczywistości jedna odmowa. Gdybyśmy mieli jeszcze jeden zasób, aby spełnić to żądanie, kolejne dwie odmowy nie miałyby miejsca. Dlatego chcemy pogrupować odmowy w raporcie, umożliwiając użytkownikowi określenie przedziału czasu, w którym powinny być grupowane. Np. Jeśli mamy odmowy (dla użytkownika 1 w funkcji 1) w sygnaturach czasowych: 1,2,24,26,27,45 i użytkownik chce zgrupować odmowy, które są bliżej siebie niż 4 sekundy, powinien otrzymać coś takiego: 1 (x2), 24 (x3), 45 (x1). Można założyć, że odstępy między prawdziwymi zaprzeczeniami są znacznie większe niż między duplikatami.
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;
Następnie, aby co 5 sekund wyświetlać odmowy ze strony użytkownika 1 i 2 dotyczące funkcji 3 i 4, wystarczy, że:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
Używam widoku, ponieważ w nim łatwo jest filtrować dane i używać ich jawnie w siatce jQuery, automatycznie porządkować, ograniczać liczbę rekordów i tak dalej.
Ale to tylko brzydkie obejście. Czy jest na to właściwy sposób?