2

このクエリは、「Microsoft SQL Server 2008-データベース開発」(本をお持ちの場合は26ページ)からのものです。そして、この本でクエリが見つかったので、AdventureWorks2008データベースに対して実行しています。質問は投稿された最初のクエリによって発生しますが、回避策を含む2番目のクエリが以下にあります。

質問: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
4

2 に答える 2

1

「ROLLUP句の後にHAVING句が適用されているため、これらの行が欠落している」ことに同意します。行を元に戻す 1 つの方法は、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
于 2015-10-17T21:43:53.127 に答える
0

ROLLUP 句の後に HAVING 句が適用され、これらの行の MIN(ListPrice) が 200 未満であるため、これらの行が欠落しています ( ProductSubcategoryId ProductCategoryId 2 の合計は 20.24、総計は 2.29 です)。

2 番目のクエリと同じ結果を得るには、次を使用することもできます。

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
于 2012-12-22T09:44:43.217 に答える