分组集中的列不应该是= SQL Server错误,或者更可能是我不理解分组集?

问题描述

我正在sql Server 2019 Developer版本上运行以下脚本。您可以在自己的sql Server上运行此程序,任何数据库都可以(不需要特定的架构)。

在脚本的底部,我在GROUP BY子句中查询了2个分组集。第二个分组集包含一个表达式作为分组集中的唯一列,我在SELECT子句中将相同的表达式作为名为“ Month”的列输出。由于该分组集而呈现的行将本月列输出为NULL。

我不希望这样。我希望任何输出与在分组集中指定的列相同的列都应包含对该分组的行进行分组的值。简而言之,我的结果集中的每一行在Month列中都应该有一个值,因为该列的表达式在我的两个分组集中。

我是否错误地考虑了这一点?通过运行此脚本在sql Server上尝试一下...

查询

IF OBJECT_ID('tempdb..#InventoryItemBatch') IS NOT NULL
    DROP TABLE #InventoryItemBatch
CREATE TABLE #InventoryItemBatch
(
    [Id] [bigint] IDENTITY(1,1) NOT NULL,[Quantity] [int] NOT NULL,[BatchNumber] [varchar](200) NULL,[InventoryDate] [date] NOT NULL,[QuantityRemoved] [int] NOT NULL,[QuantityRemaining]  AS ([Quantity]-[QuantityRemoved]),[PricePerUnit] [decimal](18,2) NULL,)

SET NOCOUNT ON
SET IDENTITY_INSERT #InventoryItemBatch ON

MERGE INTO #InventoryItemBatch AS Target
USING (VALUES
  (144,543,'Q','1980-11-17',751.24),(1274,1,'S1','1980-08-17',0.00),(1469,609,'QA','1980-06-27',778.05),(1470,95,'QC','1980-11-24',887.99),(1473,120,'QB','1980-11-14',867.20),(1475,231,'QE','1980-05-15',783.09),(1476,109,'1980-04-10',(1552,'1980-05-28',3465.00),(3082,'1980-05-30',20020.00),(4396,'1980-05-31',(4702,(5114,(5337,'1978-04-07',1250.00),(5549,(6152,(6233,'1980-07-22',(7616,(9444,'1980-04-30',(10821,'1980-05-21',1480.00),(11299,'1980-09-14',1700.00),(17432,'1980-02-18',1222.00),(20492,'1980-02-12',2040.00),(22588,'1980-01-01',(26842,1593.00),(34323,'1980-03-27',1219.00),(34334,(35223,(35379,(36384,(36395,'1980-07-13',(43278,'1978-06-09',850.00),(43998,'1978-08-18',935.00),(47460,'1978-03-15',2276.00),(47944,(48926,'1978-09-28',1350.00),(49166,'1978-05-12',1602.00),(49248,(49300,(57492,(57499,'1979-06-30',963.00),(57524,'1980-03-03',0.00)
) AS Source ([Id],[Quantity],[BatchNumber],[InventoryDate],[QuantityRemoved],[PricePerUnit])
ON (Target.[Id] = Source.[Id])
WHEN NOT MATCHED BY TARGET THEN
 INSERT([Id],[PricePerUnit])
 VALUES(Source.[Id],Source.[Quantity],Source.[BatchNumber],Source.[InventoryDate],Source.[QuantityRemoved],Source.[PricePerUnit])
;

SET IDENTITY_INSERT #InventoryItemBatch  OFF
SET NOCOUNT OFF


-- offending query
SELECT
    'Grouping-Month' = GROUPING(CONVERT(VARCHAR,YEAR(iib.InventoryDate)) + '.' + CONVERT(VARCHAR,FORMAT(iib.InventoryDate,'MM'))),'Grouping-Id' = GROUPING(iib.Id),'Grouping-DatePurchased' = GROUPING(iib.InventoryDate)

      -- this column should have a value in *eveny* row but is missing values for rows produced by the second grouping set,[Month] = CONVERT(VARCHAR,'MM')),Id = iib.Id,DatePurchased = iib.InventoryDate,SumpurchaseAmt = Sum(iib.PricePerUnit * iib.Quantity)

FROM #InventoryItemBatch iib
GROUP BY
    GROUPING SETS (
        (
            CONVERT(VARCHAR,iib.Id,iib.InventoryDate
        ),(
            -- this is the grouping expression that I'm not seeing a value for
            CONVERT(VARCHAR,'MM'))
        )
    )

部分输出

enter image description here

其他信息:

我还注意到,如果您从 first 分组集中删除“ iib.InventoryDate”列(并且还将其从SELECT子句中删除),则实际上会修复 >我在这里提到的问题... second 分组集正在输出的行实际上确实包含Month列中的那些缺失值。奇怪的!! (对吗?)

这对我来说就像个虫子。我误会了吗?

解决方法

重写查询,以便明确引入[Month]

with cte as (
    select  [Id],[Quantity],[BatchNumber],[InventoryDate],[QuantityRemoved],[QuantityRemaining],[PricePerUnit],[Month] = CONVERT(VARCHAR,YEAR(InventoryDate)) + '.' + CONVERT(VARCHAR,FORMAT(InventoryDate,'MM'))
    from #InventoryItemBatch     
)

-- offending query
SELECT
    'Grouping-Month' = GROUPING([Month]),'Grouping-Id' = GROUPING(iib.Id),'Grouping-DatePurchased' = GROUPING(iib.InventoryDate),[Month],Id = iib.Id,DatePurchased = InventoryDate,SumPurchaseAmt = Sum(iib.PricePerUnit * iib.Quantity)

FROM cte iib
GROUP BY
    GROUPING SETS (
        (
              iib.Id,iib.InventoryDate,[Month]   
        ),(
              [Month]
        )
    );