我有2张桌子:
订单:
IdProduct (what is ordered - FK to Product table)
Price (what is the total price for offer)
Piece (i.e. count - how many products are ordered?)
产品:
Id
Name
有2条SQL语句以最优惠的价格返回产品:
声明1:
SELECT
p.Name,
MIN (Price / Piece) AS MinPrice
FROM
[ORDER] o
JOIN
Product p ON IdProduct = p.Id
GROUP BY
p.Name
声明2:
SELECT p.Name, t.MinPrice
FROM
(SELECT IdProduct, MIN(Price/Piece) AS MinPrice
FROM [Order]
GROUP BY IdProduct) t
JOIN
Product p ON p.Id = t.IdProduct
我在Microsoft SQL Server Management Studio中研究了执行计划,尽管我有以下几点观察,但它们看起来非常相似:
为什么第一个计划使用[order by name]
指令?即使我不使用T-SQL Order指令
此隐式“按名称asc排序”会减慢第一个sql的速度。当我在第二个sql中添加“按名称asc排序”时,它们的执行计划成本相同。
我猜因为以下原因,sql#2应该胜过#1:
a)。它按PK(即整数)而不是按名称(具有nvarchar
列类型,并且不进行索引)分组。
b)。仅在将应该最大化性能的第一个表分组后才连接表(相比之下,如第一个sql预期的那样,将全部2个表连接起来)-但是执行计划仍显示相同的估计执行成本。
您希望使用哪种SQL语句,为什么?也许您有自己的SQL语句版本?
答案 0 :(得分:0)
我个人更喜欢陈述2。我的理由与您期望的完全不同。
您是否意识到自己的2条语句不是为了返回相同的结果而构建的?
第一个查询不会按产品对记录进行不分组,而是按产品名称对记录进行分组。在大多数数据库中,称为name
的列从不唯一。因此,两个GROUP BY
是不相等的(也许您的测试数据会发生使两个结果相同,但这只是运气。)
这是应该写的:
SELECT
p.Name,
MIN (Price / Piece) AS MinPrice
FROM
[ORDER] o
JOIN
Product p ON IdProduct = p.Id
GROUP BY
IdProduct, p.Name /* GROUP BY PK on Product */
恕我直言,第二种语法可以很好地防止此类错误。我建议您使用它。
当您使用具有100多个表而不是您自己创建和填充的2个表的旧数据库时,这将为您省去一些麻烦,更不用说第一个语句似乎可以正常工作很长时间了,直到最后,Product.name
变得不唯一。
顺便说一句,隐式order by
暗示它没有使用PK列。它不会减慢您的查询速度。它正在订购记录以准备GROUP BY
PS:要回答有关性能的问题,您的第二条语句与我写的第二条语句应该非常相似(这要归功于查询计划器)。
有时我看到第一个陈述要慢得多,但从来没有比第二个陈述要显着快(如果存在例外,它们对我来说很罕见,所以错过了它们)。
PPS:由于您汇总了Product
中的数据,因此在WHERE
中的字段上添加Order
可能会使性能变得更复杂。
恐怕这是您每次开发新查询时都必须尝试的事情。