Eu tenho uma visão assim:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
Eu gostaria de torná-lo mais genérico, significa transformar 2 em uma variável. Eu tentei isso:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
Mas o MySQL não permite isso.
Eu encontrei uma solução alternativa feia:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
E então a visão é:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
Mas parece muito ruim, e o uso também é ruim - eu tenho que definir @MyVariable antes de cada uso da visualização.
Existe uma solução, que eu poderia usar assim:
SELECT Column FROM MyView(2) WHERE (...)
A situação concreta é a seguinte: Tenho uma tabela armazenando informações sobre a solicitação negada:
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;
Uma multiplicidade é um número de solicitações idênticas registradas no mesmo segundo. Quero exibir uma lista de negações, mas às vezes, quando o aplicativo é negado, ele tenta novamente algumas vezes apenas para ter certeza. Normalmente, quando o mesmo usuário obtém negação 3 vezes no mesmo recurso em alguns segundos, é na verdade uma negação. Se tivéssemos mais um recurso, para atender a essa solicitação, as próximas duas negações não aconteceriam. Portanto, queremos agrupar as negações no relatório, permitindo ao usuário especificar o intervalo de tempo em que as negações devem ser agrupadas. Por exemplo, se tivermos negações (para o usuário 1 no recurso 1) em carimbos de data / hora: 1,2,24,26,27,45 e o usuário quiser agrupar negações que estão mais próximas umas das outras do que 4 segundos, ele deve obter algo assim: 1 (x2), 24 (x3), 45 (x1). Podemos supor que os espaços entre negações reais são muito maiores do que entre duplicações.
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;
Então, para mostrar as negações do usuário 1 e 2 nos recursos 3 e 4 mesclados a cada 5 segundos, tudo o que você precisa fazer é:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
Eu uso a view porque nela é fácil filtrar dados e usá-los explicitamente na grade jQuery, ordenar automaticamente, limitar o número de registros e assim por diante.
Mas é apenas uma solução alternativa feia. Existe uma maneira adequada de fazer isso?
fonte
É a solução adequada no MySQL, alguns outros SQLs permitem definir Views mais exatamente.
Nota: A menos que a Visualização seja muito complicada, o MySQL a otimizará perfeitamente.
fonte
Eu vim anteriormente com uma solução alternativa diferente que não usa procedimentos armazenados, mas usa uma tabela de parâmetros e alguma mágica connection_id ().
EDIT (copiado dos comentários)
crie uma tabela que contém uma coluna chamada
connection_id
(torne-a um bigint). Coloque colunas nessa tabela para parâmetros da visualização. Coloque uma chave primária noconnection_id
. substitua na tabela de parâmetros e useCONNECTION_ID()
para preencher o valor connection_id. Na visualização, use uma junção cruzada com a tabela de parâmetros e coloqueWHERE param_table.connection_id = CONNECTION_ID()
. Isso fará a junção cruzada com apenas uma linha da tabela de parâmetros que é o que você deseja. Você pode então usar as outras colunas na cláusula where, por exemplo, whereorders.order_id = param_table.order_id
.fonte