使用group by子句时显示重复的行?

时间:2019-08-26 07:10:48

标签: sql sql-server

我编写了一个SQL查询,该查询生成了如下表。

每个业务的结果需要分组为一行。我已经尝试了很多方法,但是我无法做到这一点。我试图将最终表数据插入临时表中,然后对临时表进行分组,但这不会产生正确的输出。

;WITH Generate_Dates(Start_Date, End_Date) AS (
  SELECT
    CAST(StartDateUtc AS Date),
    CAST(
      CASE WHEN [bg].EndDateUtc IS NULL THEN GETDATE() ELSE CAST([bg].EndDateUtc AS Date) end AS Date
    )
  FROM
    BusinessGoal AS [bg] WITH (NOLOCK)
  WHERE
    [bg].Period = 'Year'
  UNION ALL
  SELECT
    DATEADD(yy, 1, Start_Date),
    End_Date
  FROM
    Generate_Dates
  WHERE
    DATEADD(yy, 1, Start_Date) < End_Date
)
SELECT
  (
    Generate_Dates.Start_Date
  ) AS "Start Period Date",
  (
    Generate_Dates.End_Date
  ) AS "End Period Date",
  [bg].BusinessRefId AS 'Brand',
  (
    CAST (
      [bg].Amount AS DECIMAL
    )
  ) AS "Committed Transaction Fee",
  (
    SELECT
      CAST (
        sum (
          (
            CASE WHEN [s].Credit = 0 THEN - [s].SettlementAmount ELSE [s].SettlementAmount END
          )
        ) AS DECIMAL
      )
  ) AS "Actual Transaction Fee",
  (
    SELECT
      TOP 1 (
        CASE [s].Culture WHEN 'en-US' THEN 'USD' WHEN 'en-CA' THEN 'CAD' WHEN 'en-IE' THEN 'EUR' WHEN 'en-AU' THEN 'AUD' WHEN 'en-NZ' THEN 'NZD' WHEN 'en-Gbg' THEN 'GbgP' WHEN 'es-MX' THEN 'MXN' WHEN 'jp-JP' THEN 'JPY' WHEN 'nbg-NO' THEN 'NOK' end
      )
    FROM
      Settlement AS [s] WITH (NOLOCK)
  ) AS "Currency"
FROM
  BusinessGoal AS [bg] WITH (NOLOCK)
  INNER JOIN Settlement AS [s] WITH (NOLOCK) ON [bg].BusinessRefId = [s].CompanyRefId
  INNER JOIN OrderProductVariant AS [opv] WITH (NOLOCK) ON
  (
    [opv].MRefId = [s].CompanyRefId
    AND [opv].Id = [s].OrderProductVariantId
  )
  INNER JOIN [Order] AS [o] WITH (NOLOCK) ON [o].Id = [opv].OrderId
  INNER JOIN Generate_Dates ON GoalType = 'CommittedTransactionFee'
WHERE
    StartDateUtc <= [s].CreatedOnUtc
    AND (
      (
        EndDateUtc >= [s].CreatedOnUtc
      )
      OR (EndDateUtc is null)
    )
GROUP BY
  Start_Date,
  End_Date,
  BusinessRefId,
  Amount

输出:

Start Period Date End Period Date brand   Committed Transaction Fee 
2019-06-07        2019-08-26  NIKE        45000
2019-06-07        2019-08-26  ADIDAS      18000 
2019-06-07        2019-08-26  ADIDAS      18000 
2019-06-14        2019-08-26  NIKE        45000
2019-06-14        2019-08-26  ADIDAS      18000
2019-06-14        2019-08-26  ADIDAS      18000 
2019-07-25        2019-08-26  NIKE        45000
2019-07-25        2019-08-26  ADIDAS      18000
2019-07-25        2019-08-26  ADIDAS      18000

1 个答案:

答案 0 :(得分:2)

这取决于您要产生的输出。

如果您希望每个业务一行,但又想返回其他列(Start Period Date, End Period Date, brand, Committed Transaction Fee),则可能将无法使用GROUP BY,因为您需要包括这些GROUP BY子句中的列。

您可以使用QUALIFY函数执行此操作,并且仍然返回列,但是必须决定如何“选择”要返回的每一行。例如:

QUALIFY ROW_NUMBER() OVER(
  PARTITION BY [bg].BusinessRefId 
  ORDER BY Generate_Dates.Start_Date DESC
) = 1

这将执行以下操作:

  1. 基于[bg].BusinessRefId将结果集行分成组
  2. 根据Generate_Dates.Start_Date
  3. 对这些组中的行进行排序
  4. 返回每个组的第一行

您可以将GROUP BY子句替换为QUALIFY

WITH Generate_Dates(Start_Date, End_Date) AS (
  SELECT
    CAST(StartDateUtc AS Date),
    CAST(
      CASE 
        WHEN [bg].EndDateUtc IS NULL THEN GETDATE() 
        ELSE CAST([bg].EndDateUtc AS Date) 
      END AS DATE
    )
  FROM BusinessGoal AS [bg] WITH (NOLOCK)
  WHERE [bg].Period = 'Year'

  UNION ALL

  SELECT
    DATEADD(yy, 1, Start_Date),
    End_Date
  FROM Generate_Dates
  WHERE DATEADD(yy, 1, Start_Date) < End_Date
)
SELECT DISTINCT
  Generate_Dates.Start_Date AS 'Start Period Date',
  Generate_Dates.End_Date AS 'End Period Date',
  [bg].BusinessRefId AS 'brand',
  CAST ([bg].Amount AS DECIMAL) AS 'Committed Transaction Fee',
  (
    SELECT
      TOP 1 CAST (
        SUM (
            CASE 
              WHEN [s].Credit = 0 THEN - [s].SettlementAmount 
              ELSE [s].SettlementAmount 
            END
        ) AS DECIMAL
      )
  ) AS 'Actual Transaction Fee',
  (
    SELECT
      TOP 1 (
        CASE [s].Culture 
          WHEN 'en-US' THEN 'USD' 
          WHEN 'en-CA' THEN 'CAD' 
          WHEN 'en-IE' THEN 'EUR' 
          WHEN 'en-AU' THEN 'AUD' 
          WHEN 'en-NZ' THEN 'NZD' 
          WHEN 'en-Gbg' THEN 'GbgP' 
          WHEN 'es-MX' THEN 'MXN' 
          WHEN 'jp-JP' THEN 'JPY' 
          WHEN 'nbg-NO' THEN 'NOK'
        END
      )
    FROM Settlement AS [s] WITH (NOLOCK)
  ) AS 'Currency'
FROM BusinessGoal AS [bg] WITH (NOLOCK)
INNER JOIN Settlement AS [s] WITH (NOLOCK) ON [bg].BusinessRefId = [s].CompanyRefId
INNER JOIN OrderProductVariant AS [opv] WITH (NOLOCK) ON
  (
    [opv].MRefId = [s].CompanyRefId
    AND [opv].Id = [s].OrderProductVariantId
  )
INNER JOIN [Order] AS [o] WITH (NOLOCK) ON [o].Id = [opv].OrderId
INNER JOIN Generate_Dates ON GoalType = 'CommittedTransactionFee'
WHERE StartDateUtc <= [s].CreatedOnUtc
AND (EndDateUtc >= [s].CreatedOnUtc OR EndDateUtc IS NULL)
QUALIFY ROW_NUMBER() OVER(
  PARTITION BY [bg].BusinessRefId 
  ORDER BY Generate_Dates.Start_Date DESC
) = 1
--GROUP BY Start_Date, End_Date, BusinessRefId, Amount, [s].Culture

此外,就像前面提到的海报一样,您不需要DISTINCT。如果您要执行的GROUP BY没有任何聚合函数,则从逻辑上讲等效于执行DISTINCT

我还没有测试过,所以不确定它是否可以工作...但是可以尝试一下。