Ich habe eine Ansicht wie diese:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
Ich möchte es allgemeiner machen, es bedeutet, 2 in eine Variable umzuwandeln. Ich habe es versucht:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
Aber MySQL erlaubt das nicht.
Ich habe eine hässliche Problemumgehung gefunden:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
Und dann ist die Ansicht:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
Aber es sieht wirklich beschissen aus und die Verwendung ist auch beschissen - ich muss die @MyVariable vor jeder Verwendung der Ansicht festlegen.
Gibt es eine Lösung, die ich so verwenden könnte:
SELECT Column FROM MyView(2) WHERE (...)
Die konkrete Situation ist wie folgt: Ich habe eine Tabelle, in der Informationen über die abgelehnte Anfrage gespeichert sind:
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;
Eine Vielzahl ist eine Anzahl identischer Anforderungen, die in derselben Sekunde aufgezeichnet wurden. Ich möchte eine Liste von Ablehnungen anzeigen, aber manchmal, wenn die Anwendung abgelehnt wird, wird sie ein paar Mal wiederholt, nur um sicherzugehen. Wenn also derselbe Benutzer innerhalb weniger Sekunden dreimal die gleiche Funktion verweigert, handelt es sich in der Regel tatsächlich um eine Ablehnung. Wenn wir noch eine Ressource hätten, um diese Anfrage zu erfüllen, würden die nächsten beiden Ablehnungen nicht passieren. Daher möchten wir die Ablehnungen im Bericht gruppieren, damit der Benutzer die Zeitspanne angeben kann, in der Ablehnungen gruppiert werden sollen. Wenn wir beispielsweise in Zeitstempeln Ablehnungen (für Benutzer 1 in Merkmal 1) haben: 1,2,24,26,27,45 und Benutzer Ablehnungen gruppieren möchten, die näher als 4 Sekunden beieinander liegen, sollte er Folgendes erhalten: 1 (x2), 24 (x3), 45 (x1). Wir können davon ausgehen, dass die Zwischenräume zwischen realen Ablehnungen viel größer sind als zwischen Duplikaten.
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;
Um die Ablehnungen von Benutzer 1 und 2 für die Funktionen 3 und 4 anzuzeigen, die alle 5 Sekunden zusammengeführt wurden, müssen Sie lediglich Folgendes tun:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
Ich verwende die Ansicht, weil es einfach ist, Daten zu filtern und explizit im jQuery-Raster zu verwenden, automatisch zu ordnen, die Anzahl der Datensätze zu begrenzen und so weiter.
Aber es ist nur eine hässliche Problemumgehung. Gibt es einen richtigen Weg, dies zu tun?
quelle
Ist die richtige Lösung in MySQL, können Sie mit einigen anderen SQLs Ansichten genauer definieren.
Hinweis: Sofern die Ansicht nicht sehr kompliziert ist, wird MySQL dies problemlos optimieren.
quelle
Ich habe mir zuvor eine andere Problemumgehung ausgedacht, bei der keine gespeicherten Prozeduren verwendet werden, sondern stattdessen eine Parametertabelle und etwas Magie von connection_id () verwendet werden.
BEARBEITEN (aus Kommentaren kopiert)
Erstellen Sie eine Tabelle, die eine Spalte mit dem Namen
connection_id
(machen Sie sie zu einem Bigint) enthält. Platzieren Sie in dieser Tabelle Spalten für Parameter für die Ansicht. Legen Sie einen Primärschlüssel auf dieconnection_id
. In die Parametertabelle ersetzen undCONNECTION_ID()
zum Auffüllen des Wertes connection_id verwenden. Verwenden Sie in der Ansicht einen Cross-Join zur Parametertabelle und setzen SieWHERE param_table.connection_id = CONNECTION_ID()
. Dadurch wird die Verknüpfung mit nur einer Zeile aus der Parametertabelle gekreuzt, was Sie möchten. Sie können dann die anderen Spalten in der where-Klausel verwenden, z. B. whereorders.order_id = param_table.order_id
.quelle