我有这样的观点:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = 2;
我想让它更通用,它意味着将2变为变量。我试过这个:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = @MyVariable;
但MySQL不允许这样做。
我找到了一个丑陋的解决方法:
CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|
然后视图是:
CREATE VIEW MyView AS
SELECT Column FROM Table WHERE Value = GetMyVariable();
但它看起来很糟糕,而且用法也很糟糕 - 我必须在每次使用视图之前设置@MyVariable。
是否有解决方案,我可以这样使用:
SELECT Column FROM MyView(2) WHERE (...)
具体情况如下: 我有一个表存储有关拒绝请求的信息:
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;
多重性是在同一秒内记录的许多相同请求。我想显示一个拒绝列表,但有时候,当应用程序被拒绝时,它会重试几次以确保。通常情况下,当同一个用户在几秒钟内对同一个功能进行3次拒绝时,实际上是一次拒绝。如果我们还有一个资源,为了满足这个要求,接下来的两个拒绝就不会发生。因此,我们希望将报告中的拒绝分组,允许用户指定拒绝应分组的时间跨度。例如。如果我们在时间戳中拒绝(对于功能1上的用户1):1,2,24,26,27,45并且用户想要对彼此更接近的拒绝进行分组,那么他应该得到这样的结果:1 (x2),24(x3),45(x1)。我们可以假设,真实否认之间的空间比重复之间的空间大得多。我用以下方式解决了这个问题:
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;
然后,要显示来自用户1和2的拒绝功能3和4每5秒合并一次,您需要做的就是:
SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);
我使用视图,因为在其中很容易过滤数据并在jQuery网格中显式使用它,自动排序,限制记录数等等。
但这只是一个丑陋的解决方法。有没有正确的方法来做到这一点?
答案 0 :(得分:130)
实际上如果你创建了func:
create function p1() returns INTEGER DETERMINISTIC NO SQL return @p1;
并查看:
create view h_parm as
select * from sw_hardware_big where unit_id = p1() ;
然后您可以使用参数调用视图:
select s.* from (select @p1:=12 p) parm , h_parm s;
我希望它有所帮助。
答案 1 :(得分:19)
CREATE VIEW MyView AS
SELECT Column, Value FROM Table;
SELECT Column FROM MyView WHERE Value = 1;
在MySQL中是否是正确的解决方案,其他一些SQL可以让您更准确地定义视图。
注意:除非View非常复杂,否则MySQL会很好地优化它。
答案 2 :(得分:1)
我之前提出了一种不使用存储过程的不同解决方法,而是使用参数表和一些connection_id()魔术。
编辑(从评论中删除)
创建一个包含名为connection_id
的列的表(使其成为bigint)。在该表中放置列以获取视图的参数。将主键放在connection_id
上。替换到参数表并使用CONNECTION_ID()
填充connection_id值。在视图中使用交叉连接到参数表并放置WHERE param_table.connection_id = CONNECTION_ID()
。这将与参数表中只有一行交叉连接,这是您想要的。然后,您可以使用where子句中的其他列,例如orders.order_id = param_table.order_id
。