【问题标题】:Counter column in a SQL QuerySQL 查询中的计数器列
【发布时间】:2016-05-18 09:26:02
【问题描述】:

我有两个表,我通过 INNER JOIN 链接。它们是 Invoice Header 表和 Invoice Lines 表。

我想添加的是某种计数器列,它会为每个唯一的发票编号给我一个 1,而如果发票有多个行项目,则为任何重复的发票编号给我一个 0。然后,当我稍后分析我的数据时,它将允许我对 Excel 中的各个列进行计数。基本上是计数,但只在左表的记录上,忽略右表。

我只是不知道如何使用 COUNT() 或 CASE 来使其工作。有可能吗?

这是我的查询:

SELECT P.DocNum
     , L.LineNum
     , P.DocCur
     , P.DocTotalFC
     , P.DocTotal
     , CASE 
         WHEN LEFT(L.AcctCode, 1) = '7'  THEN 'Admin'
         WHEN LEFT(L.AcctCode, 2) = '15' THEN 'Admin'
         WHEN L.AcctCode = '11501'       THEN 'MX'
         WHEN LEFT(L.Project, 1) = 'W'   THEN 'MX'
         WHEN L.OcrCode2 = '570'         THEN 'MEC'
         WHEN L.OcrCode2 = '590'         THEN 'ZHU'
         ELSE 'Flight Ops'
       END AS 'Type'
     , L.AcctCode AS 'Account'
     , L.OcrCode  AS 'Aircraft'
     , L.OcrCode2 AS 'Department'
     , L.OcrCode3 AS 'Business Unit'
     , L.Project  AS 'Project'               
     , L.LineTotal
FROM OPCH P
   INNER JOIN PCH1 L ON P.DocEntry = L.DocEntry
WHERE P.DocDate BETWEEN '2016-01-01' AND '2016-03-31'  
ORDER BY P.DocNum, L.LineNum

高度赞赏任何提示。

提前致谢。

【问题讨论】:

  • 发票号是哪一个?哪个版本的SQL Server
  • 发票编号为DocNum字段。服务器是 SQL Server 2008。Sagi 的分区上的 row_number 可以解决问题:)

标签: sql-server count inner-join


【解决方案1】:

我认为你需要的是 ROW_NUMBER() 而不是 COUNT()

SELECT P.DocNum
     , L.LineNum
     , P.DocCur
     , P.DocTotalFC
     , P.DocTotal
     , CASE 
         WHEN LEFT(L.AcctCode, 1) = '7'  THEN 'Admin'
         WHEN LEFT(L.AcctCode, 2) = '15' THEN 'Admin'
         WHEN L.AcctCode = '11501'       THEN 'MX'
         WHEN LEFT(L.Project, 1) = 'W'   THEN 'MX'
         WHEN L.OcrCode2 = '570'         THEN 'MEC'
         WHEN L.OcrCode2 = '590'         THEN 'ZHU'
         ELSE 'Flight Ops'
       END AS 'Type'
     , L.AcctCode AS 'Account'
     , L.OcrCode  AS 'Aircraft'
     , L.OcrCode2 AS 'Department'
     , L.OcrCode3 AS 'Business Unit'
     , L.Project  AS 'Project'               
     , L.LineTotal
     , CASE WHEN ROW_NUMBER() OVER(PARTITION BY p.docnum ORDER BY p.docDate) > 1
            then 0
            else 1
       end as rnk
FROM OPCH P
   INNER JOIN PCH1 L ON P.DocEntry = L.DocEntry
WHERE P.DocDate BETWEEN '2016-01-01' AND '2016-03-31'  
ORDER BY P.DocNum, L.LineNum

您没有提供足够的详细信息来了解哪一列是唯一发票编号,以及您通过哪一列确定谁是第一个(获得值 1)和重复项(获得值 0)。我使用docnum 作为发票编号,并使用docdate 作为列来确定哪些是重复的,如果需要,请调整它。

如果顺序无关紧要 - 它完全是重复的,并且哪条记录是重复的无关紧要,那么按部分的顺序无关紧要。

【讨论】:

  • DocNum 是发票编号,正如您正确假设的那样。非常感谢。我知道 row_number() 函数,但不知道“分区依据”技巧。太棒了,谢谢。
【解决方案2】:

由于我不知道基于假设的确切数据,我使用了 Row_number 和 Case 条件,我们可以得到 1 表示正常值,0 表示重复值

SELECT P.DocNum
     , L.LineNum
     , P.DocCur
     , P.DocTotalFC
     , P.DocTotal
     , CASE 
         WHEN LEFT(L.AcctCode, 1) = '7'  THEN 'Admin'
         WHEN LEFT(L.AcctCode, 2) = '15' THEN 'Admin'
         WHEN L.AcctCode = '11501'       THEN 'MX'
         WHEN LEFT(L.Project, 1) = 'W'   THEN 'MX'
         WHEN L.OcrCode2 = '570'         THEN 'MEC'
         WHEN L.OcrCode2 = '590'         THEN 'ZHU'
         ELSE 'Flight Ops'
       END AS 'Type'
     , L.AcctCode AS 'Account'
     , L.OcrCode  AS 'Aircraft'
     , L.OcrCode2 AS 'Department'
     , L.OcrCode3 AS 'Business Unit'
     , L.Project  AS 'Project'               
     , L.LineTotal
     , CASE WHEN ROW_NUMBER()OVER(PARTITION BY  P.DocNum,L.LineNum ORDER BY (SELECT NULL)) = 1 THEN 1 ELSE 0 END SummaryValues
FROM OPCH P
   INNER JOIN PCH1 L ON P.DocEntry = L.DocEntry
WHERE P.DocDate BETWEEN '2016-01-01' AND '2016-03-31'  
ORDER BY P.DocNum, L.LineNum

【讨论】:

    【解决方案3】:
    ;with cte as (
        SELECT
            a.DocEntry, joincounter = count(b.DocEntry)
        FROM
            OPCH P AS a 
            INNER JOIN PCH1 AS b ON a.DocEntry = b.DocEntry
        group by a.DocEntry
    )
    SELECT 
        case 
            when cte.joincounter > 1 then 0
            else cte.joincounter 
        end as joincounter
    
        ,P.DocNum
        , L.LineNum
        , P.DocCur
        , P.DocTotalFC
        , P.DocTotal
        , CASE 
            WHEN LEFT(L.AcctCode, 1) = '7'  THEN 'Admin'
            WHEN LEFT(L.AcctCode, 2) = '15' THEN 'Admin'
            WHEN L.AcctCode = '11501'       THEN 'MX'
            WHEN LEFT(L.Project, 1) = 'W'   THEN 'MX'
            WHEN L.OcrCode2 = '570'         THEN 'MEC'
            WHEN L.OcrCode2 = '590'         THEN 'ZHU'
            ELSE 'Flight Ops'
        END AS 'Type'
        , L.AcctCode AS 'Account'
        , L.OcrCode  AS 'Aircraft'
        , L.OcrCode2 AS 'Department'
        , L.OcrCode3 AS 'Business Unit'
        , L.Project  AS 'Project'               
        , L.LineTotal
    FROM 
        OPCH P
        INNER JOIN PCH1 L ON P.DocEntry = L.DocEntry
        inner join cte on cte.DocEntry = P.DocEntry
    WHERE
        P.DocDate >= '2016-01-01' 
        AND P.DocDate < '2016-03-31'  
    ORDER BY
        P.DocNum, L.LineNum
    

    【讨论】:

      猜你喜欢
      • 2013-09-11
      • 2012-06-08
      • 1970-01-01
      • 2014-10-27
      • 2017-11-30
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多