此查询来自“Microsoft SQL Server 2008 - 数据库开发”(如果您有本书,请参见第26页)。并且,由于在本书中找到了查询,因此我正在运行AdventureWorks2008数据库。问题出现在第一个查询中,但下面有第二个查询,其中包含一个解决方法。
问题:为什么我们在使用WITH ROLLUP和HAVING子句时缺少ProductCategoryID = 2的小计行,以及下一个查询的总行?
所有ProductCategoryID都有一个小计行,删除HAVING子句时结果集中包含一个总行。
查询:
SELECT
Production.ProductCategory.ProductCategoryID
, Production.Product.ProductSubcategoryID
, AVG(ListPrice) AS 'Average'
, MIN(ListPrice) AS 'Minimum'
, MAX(ListPrice) AS 'Maximum'
FROM Production.Product
JOIN Production.ProductSubcategory ON Production.ProductSubcategory.ProductSubcategoryID = Production.Product.ProductSubcategoryID
JOIN Production.ProductCategory ON Production.ProductSubcategory.ProductCategoryID = Production.ProductCategory.ProductCategoryID
WHERE
ListPrice <> 0
GROUP BY
Production.ProductCategory.ProductCategoryID
, Production.Product.ProductSubcategoryID
WITH ROLLUP
HAVING
MIN(ListPrice) > 200
结果:
ProductCategoryId ProductSubcategoryId Average Minimum Maximum
1 1 1683.365 539.99 3399.99
1 2 1597.45 539.99 3578.27
1 3 1425.2481 742.35 2384.07
1 NULL 1586.737 539.99 3578.27
2 12 678.2535 249.79 1364.50
2 14 780.0436 337.22 1431.50
2 16 631.4155 333.42 1003.91
查询结果我希望在原始查询中看到的结果(通过用子查询替换我们的HAVING子句来解决问题):
SELECT
Production.ProductCategory.ProductCategoryID
, Production.Product.ProductSubcategoryID
, AVG(ListPrice) AS 'Average'
, MIN(ListPrice) AS 'Minimum'
, MAX(ListPrice) AS 'Maximum'
FROM Production.Product
JOIN Production.ProductSubcategory ON Production.ProductSubcategory.ProductSubcategoryID = Production.Product.ProductSubcategoryID
JOIN Production.ProductCategory ON Production.ProductSubcategory.ProductCategoryID = Production.ProductCategory.ProductCategoryID
WHERE
ListPrice <> 0
AND Production.Product.ProductSubcategoryID IN
(
SELECT
Production.Product.ProductSubcategoryID
FROM Production.Product
GROUP BY
Production.Product.ProductSubcategoryID
HAVING
MIN(ListPrice) > 200
)
GROUP BY
Production.ProductCategory.ProductCategoryID
, Production.Product.ProductSubcategoryID
WITH ROLLUP
结果:
ProductCategoryId ProductSubcategoryId Average Minimum Maximum
1 1 1683.365 539.99 3399.99
1 2 1597.45 539.99 3578.27
1 3 1425.2481 742.35 2384.07
1 NULL 1586.737 539.99 3578.27
2 12 678.2535 249.79 1364.50
2 14 780.0436 337.22 1431.50
2 16 631.4155 333.42 1003.91
2 NULL 710.1015 249.79 1431.50
NULL NULL 1193.2472 249.79 3578.27
答案 0 :(得分:1)
我同意“由于在ROLLUP子句之后应用了HAVING子句,因此缺少那些行”。 获取行的一种方法是从以下位置更改HAVING子句:
HAVING
MIN(ListPrice) > 200
为:
HAVING
(MIN(ListPrice) > 200)
or (Grouping (Production.ProductCategory.ProductCategoryID) = 1)
or (Grouping (Production.Product.ProductSubcategoryID) = 1)
此外,应该有一个订单条款。类似的东西:
Order by Case
When (Grouping (Production.ProductCategory.ProductCategoryID) = 1) Then 1
Else 0
End,
Production.ProductCategory.ProductCategoryID,
Case
When (Grouping (Production.Product.ProductSubcategoryID) = 1) Then 1
Else 0
End,
Production.Product.ProductSubcategoryID
答案 1 :(得分:0)
缺少那些行,因为在ROLLUP子句之后应用了HAVING子句,而对于那些行,MIN(ListPrice)小于200(对于 ProductSubcategoryId ProductCategoryId 2的总数为20.24,对于2.29为总计)。
要获得与第二个查询相同的结果,您还可以使用:
SELECT
c.ProductCategoryID
, s.ProductSubcategoryID
, AVG(ListPrice) AS 'Average'
, MIN(ListPrice) AS 'Minimum'
, MAX(ListPrice) AS 'Maximum'
FROM (
SELECT *, MIN(ListPrice) OVER (PARTITION BY ProductSubcategoryID) AS MinimumListPriceForSubcategory
FROM Production.Product
) p
JOIN Production.ProductSubcategory s ON s.ProductSubcategoryID = p.ProductSubcategoryID
JOIN Production.ProductCategory c ON s.ProductCategoryID = c.ProductCategoryID
WHERE ListPrice <> 0
AND MinimumListPriceForSubcategory>200
GROUP BY c.ProductCategoryID, s.ProductSubcategoryID
WITH ROLLUP