我有一个查询,需要根据几个字段选择计算值,但前提是计算结果与现有字段不同。所以,让我们说它看起来像这样:
SELECT ProductID
, PastProfits
, ((UnitPrice - UnitCost) * UnitsSold) AS CurrentProfits
FROM product
WHERE UnitsSold > 10
HAVING CurrentProfits <> PastProfits;
现在,问题是我的结果集中实际上并不需要PastProfits
。但是,如果我将PastProfits
退出SELECT
,我就无法在HAVING
子句中访问它。我可以想到几种解决方法:
如上所示,在PastProfits
中加入SELECT
,并比较HAVING
子句中的字段。 (或者我可以将整个事物放在外部查询中带有WHERE
子句的子查询中,但可能没有任何意义。)
添加GROUP BY ProductID, PastProfits
,以便在HAVING
子句中显示该字段。
使用用户定义的变量将计算结果存储在WHERE
子句中。例如:
SELECT ProductID
, @profit AS CurrentProfits
FROM product
WHERE UnitsSold > 10
AND (@profit:=((UnitPrice - UnitCost) * UnitsSold)) <> PastProfits;
无论如何,我的问题是:这些方法的相对优缺点是什么?他们中的任何一个都更加正确吗?#34;?哪一个可能表现最好?我错过了其他方法吗?
答案 0 :(得分:0)
一种选择是将谓词移动到WHERE
子句;您需要重复表达式而不是引用分配给SELECT列表中表达式的别名,例如
SELECT ProductID
, ((UnitPrice - UnitCost) * UnitsSold) AS CurrentProfits
FROM product
WHERE UnitsSold > 10
AND ((UnitPrice - UnitCost) * UnitsSold) <> PastProfits
如果您的目标是避免重复表达式,则可以使用内联视图(以性能损失为代价)。将当前查询用作外部查询的行源(派生表):
SELECT v.ProductID
, v.CurrentProfits
FROM (
SELECT ProductID
, PastProfits
, ((UnitPrice - UnitCost) * UnitsSold) AS CurrentProfits
FROM product
WHERE UnitsSold > 10
HAVING CurrentProfits <> PastProfits
) v
用户定义的变量似乎不能提供可靠的解决方案; MySQL文档警告不要在这样的语句中使用用户定义的变量;这种行为可能是出乎意料的。
答案 1 :(得分:0)
&#34;正确&#34;编写查询的方法是复制where
子句中的表达式:
SELECT ProductID, ((UnitPrice - UnitCost) * UnitsSold) as CurrentProfits
FROM product
WHERE UnitsSold > 10 and ((UnitPrice - UnitCost) * UnitsSold) <> PastProfits;
这是标准SQL,它不需要使用任何特定于MySQL的扩展(例如使用having
而不使用group by
)。如果您没有使用MySQL,我建议:
SELECT ProductId, CurrentProfits
FROM (SELECT ProductID, ((UnitPrice - UnitCost) * UnitsSold) AS CurrentProfits
FROM product
WHERE UnitsSold > 10
) p
WHERE CurrentProfits <> PastProfits;
唉,在MySQL中,这可能会更加昂贵,因为子查询已经实现了。
在你的三个选择中,(1)和(2)是合理的。
第三个选项对变量的处理做出假设。一般来说,MySQL不保证变量处理的顺序,所以我会避免这种情况。