【问题标题】:Avoid SQL Pivot returning duplicate rows避免 SQL Pivot 返回重复行
【发布时间】:2019-09-03 19:02:49
【问题描述】:

我有以下 SQL 脚本,它在 PIVOT 中返回重复值。如何将这些重复记录合并到一行。

请检查下图的结果集。

SELECT *
FROM   (SELECT X.stockcode,
               X.description,
               X.pack,
               X.location,
               X.lname,
               X.qty,
               Y.stockcode AS StockCode2,
               y.periodname,
               Y.months,
               Y.saleqty
        FROM   (SELECT dbo.stock_items.stockcode,
                       dbo.stock_items.description,
                       dbo.stock_items.pack,
                       dbo.stock_loc_info.location,
                       dbo.stock_locations.lname,
                       dbo.stock_loc_info.qty
                FROM   dbo.stock_locations
                       INNER JOIN dbo.stock_loc_info
                               ON dbo.stock_locations.locno = dbo.stock_loc_info.location
                       LEFT OUTER JOIN dbo.stock_items
                                    ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
                WHERE  ( dbo.stock_items.status = 's' )) AS X
               LEFT OUTER JOIN (SELECT dbo.dr_invlines.stockcode,
                                       ( 12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate) ) % 12 + 1 AS Months,
                                       Sum(dbo.dr_invlines.quantity)                                                          AS SaleQty,
                                       dbo.period_status.periodname
                                FROM   dbo.dr_trans
                                       INNER JOIN dbo.period_status
                                               ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
                                       LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
                                                       RIGHT OUTER JOIN dbo.dr_invlines
                                                                     ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode
                                                    ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno
                                WHERE  ( STOCK_ITEMS_1.status = 'S' )
                                       AND ( dbo.dr_trans.transtype IN ( 1, 2 ) )
                                       AND ( dbo.dr_trans.transdate >= Dateadd(m, -6, Getdate()) )
                                GROUP  BY dbo.dr_invlines.stockcode,
                                          Datepart(month, dbo.dr_trans.transdate),
                                          dbo.period_status.periodname) AS Y
                            ON X.stockcode = Y.stockcode) z
       PIVOT (Sum(saleqty) FOR [months] IN ([1],[2],[3],[4],[5],[6])) AS pivoted  

【问题讨论】:

  • 有一列PERIODNAME是不同的值。您的预期结果是什么?
  • “Feed”只需要的列。正如 D-Shih 所暗示的,从您的查询中删除 PERIODNAME。
  • 然后我将删除期间名称列

标签: sql sql-server pivot


【解决方案1】:

编辑:我错过了问题的根本原因是包含导致感知重复的 periodname 列。我将其保留为显示 CTE 使用情况的通用解决方案,因为如果您想对数据透视结果进行额外的过滤/转换,它仍然很有用

一种方法是获取数据透视查询的结果并通过 SELECT DISTINCT 查询运行它。

将您的数据透视查询包装为 CTE 并使用它来提供下面的 SELECT DISTINCT 的示例(请注意:未经测试,但在我的 SSMS 中解析为有效)

WITH PivotResults_CTE (
    stockcode,
    description,
    pack,
    location,
    lname,
    qty,
    StockCode2,
    periodname,
    months,
    saleqty
)
AS (
    SELECT *
    FROM (
        SELECT X.stockcode
            ,X.description
            ,X.pack
            ,X.location
            ,X.lname
            ,X.qty
            ,Y.stockcode AS StockCode2
            ,y.periodname
            ,Y.months
            ,Y.saleqty
        FROM (
            SELECT dbo.stock_items.stockcode
                ,dbo.stock_items.description
                ,dbo.stock_items.pack
                ,dbo.stock_loc_info.location
                ,dbo.stock_locations.lname
                ,dbo.stock_loc_info.qty
            FROM dbo.stock_locations
            INNER JOIN dbo.stock_loc_info ON dbo.stock_locations.locno = dbo.stock_loc_info.location
            LEFT OUTER JOIN dbo.stock_items ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
            WHERE (dbo.stock_items.STATUS = 's')
            ) AS X
        LEFT OUTER JOIN (
            SELECT dbo.dr_invlines.stockcode
                ,(12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate)) % 12 + 1 AS Months
                ,Sum(dbo.dr_invlines.quantity) AS SaleQty
                ,dbo.period_status.periodname
            FROM dbo.dr_trans
            INNER JOIN dbo.period_status ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
            LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
            RIGHT OUTER JOIN dbo.dr_invlines ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno WHERE (STOCK_ITEMS_1.STATUS = 'S')
                AND (
                    dbo.dr_trans.transtype IN (
                        1
                        ,2
                        )
                    )
                AND (dbo.dr_trans.transdate >= Dateadd(m, - 6, Getdate()))
            GROUP BY dbo.dr_invlines.stockcode
                ,Datepart(month, dbo.dr_trans.transdate)
                ,dbo.period_status.periodname
            ) AS Y ON X.stockcode = Y.stockcode
        ) z
    PIVOT(Sum(saleqty) FOR [months] IN (
                [1]
                ,[2]
                ,[3]
                ,[4]
                ,[5]
                ,[6]
                )) AS pivoted
)
SELECT DISTINCT *
FROM
    PivotResults_CTE
; 

另外请注意,上面包含的 sql 可能看起来与原始的略有不同,但这只是因为我通过重新格式化程序运行它以确保我理解它的结构。

换句话说,您的数据透视查询的基本 CTE 包装器是:

WITH PivotResults_CTE (
    Field1,
    Field2,
    ...
)
AS (
    YOUR_PIVOT_QUERY_HERE
)
SELECT DISTINCT *
FROM
    PivotResults_CTE
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    相关资源
    最近更新 更多