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?
źródło
CREATE VIEW MyView AS SELECT Column, Value FROM Table; SELECT Column FROM MyView WHERE Value = 1;
To właściwe rozwiązanie w MySQL, inne SQL pozwalają na dokładniejsze definiowanie widoków.
Uwaga: O ile widok nie jest bardzo skomplikowany, MySQL zoptymalizuje to dobrze.
źródło
Wcześniej wymyśliłem inne obejście, które nie używa procedur składowanych, ale zamiast tego używa tabeli parametrów i pewnej magii connection_id ().
EDYTUJ (skopiowane z komentarzy)
utwórz tabelę zawierającą kolumnę o nazwie
connection_id
(zmień ją na bigint). Umieść kolumny w tej tabeli dla parametrów widoku. Umieść klucz podstawowy naconnection_id
. zamienić w tabeli parametrów i użyćCONNECTION_ID()
do wypełnienia wartości connection_id. W widoku użyj połączenia krzyżowego do tabeli parametrów i wstawWHERE param_table.connection_id = CONNECTION_ID()
. Spowoduje to sprzężenie krzyżowe tylko z jednym wierszem z tabeli parametrów, czego chcesz. Następnie możesz użyć innych kolumn w klauzuli where, na przykład gdzieorders.order_id = param_table.order_id
.źródło