Tengo una vista como esta:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
Me gustaría hacerlo más genérico, significa cambiar 2 en una variable. Probé esto:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
Pero MySQL no permite esto.
Encontré una fea solución:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
Y luego la vista es:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
Pero se ve realmente horrible, y el uso también es malo: tengo que configurar @MyVariable antes de cada uso de la vista.
¿Hay una solución que pueda usar así?
SELECT Column FROM MyView(2) WHERE (...)
La situación concreta es la siguiente: tengo una tabla que almacena información sobre la solicitud denegada:
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;
Una multiplicidad es una cantidad de solicitudes idénticas registradas en el mismo segundo. Quiero mostrar una lista de rechazos, pero a veces, cuando se rechaza la solicitud, vuelve a intentarlo un par de veces solo para asegurarme. Por lo general, cuando el mismo usuario recibe una denegación 3 veces en la misma función en un par de segundos, en realidad es una denegación. Si tuviéramos un recurso más, para cumplir con esta solicitud, las siguientes dos denegaciones no sucederían. Por lo tanto, queremos agrupar las denegaciones en un informe, lo que permite al usuario especificar el período de tiempo en el que se deben agrupar las denegaciones. Por ejemplo, si tenemos denegaciones (para el usuario 1 en la función 1) en las marcas de tiempo: 1, 2, 24, 26, 27, 45 y el usuario desea agrupar las denegaciones que están más cerca entre sí que 4 segundos, debería obtener algo como esto: 1 (x2), 24 (x3), 45 (x1). Podemos suponer que los espacios entre negaciones reales son mucho más grandes que entre duplicaciones.
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;
Luego, para mostrar las denegaciones del usuario 1 y 2 en las funciones 3 y 4 fusionadas cada 5 segundos, todo lo que tiene que hacer es:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
Utilizo la vista porque en ella es fácil filtrar datos y usarlos explícitamente en la cuadrícula jQuery, ordenar automáticamente, limitar el número de registros, etc.
Pero es solo una fea solución. ¿Existe una forma adecuada de hacer esto?
fuente
Es la solución adecuada en MySQL, algunos otros SQL le permiten definir Vistas con mayor precisión.
Nota: A menos que la vista sea muy complicada, MySQL optimizará esto muy bien.
fuente
Anteriormente se me ocurrió una solución alternativa diferente que no usa procedimientos almacenados, sino que usa una tabla de parámetros y algo de magia connection_id ().
EDITAR (copiado de los comentarios)
cree una tabla que contenga una columna llamada
connection_id
(hágalo un bigint). Coloque columnas en esa tabla para los parámetros de la vista. Ponga una clave principal en elconnection_id
. reemplácelo en la tabla de parámetros y utilíceloCONNECTION_ID()
para completar el valor de connection_id. En la vista, use una combinación cruzada con la tabla de parámetros y coloqueWHERE param_table.connection_id = CONNECTION_ID()
. Esto cruzará la unión con solo una fila de la tabla de parámetros que es lo que desea. Luego puede usar las otras columnas en la cláusula where, por ejemplo whereorders.order_id = param_table.order_id
.fuente