代码之家  ›  专栏  ›  技术社区  ›  Archangel33

从表中选择前N行包含N的列

  •  3
  • Archangel33  · 技术社区  · 12 年前

    TSQL 2008 R2

    我有重复的行项目,每个项目都有自己的唯一ID,用于给定的PO#。我需要删除重复项。我不知道每个采购订单有多少份副本。因为有一个#LineItems,我知道我只想要第一个(顶部)x(#lineIems)行项目。

    我有一张这样的桌子:

    LineitemID PO#     #LineItems
    ---------- ------- ----------
    11111111   12345   3
    22222222   12345   3
    33333333   12345   3
    44444444   12345   3
    55555555   12345   3
    66666666   12345   3
    77777777   54321   2
    88888888   54321   2
    99999999   54321   2
    10101010   54321   2
    ...  
    

    我需要一张这样的桌子:

    LineitemID PO#     #LineItems
    ---------- ------- ----------
    11111111   12345   3
    22222222   12345   3
    33333333   12345   3
    77777777   54321   2
    88888888   54321   2
    ...  
    

    所以基本上有没有这样的方法:

    DECLARE @top int = (SELECT TOP 1 FROM tblLineItems t WHERE t.PO# = @PO)
    
    SELECT TOP (@top)
    FROM tblLineItems
    

    并根据每个采购订单执行此操作#

    2 回复  |  直到 12 年前
        1
  •  2
  •   Mikael Engver    12 年前

    删除了facepalm后的第一个答案。

    您的示例唯一的问题是在TOP查询中没有ORDER BY,这可能会以任何顺序提取结果。此查询假定您是按LineItemID(整数类型)ASC排序的。

    DECLARE @LineItems TABLE
    (
        LineItemID INT
        , PO INT
        , NumLineItems INT
    )
    
    INSERT INTO @LineItems (LineItemID, PO, NumLineItems)
    SELECT 11111111,   12345,   3
    UNION ALL SELECT 22222222,   12345,   3
    UNION ALL SELECT 33333333,   12345,   3
    UNION ALL SELECT 44444444,   12345,   3
    UNION ALL SELECT 55555555,   12345,   3
    UNION ALL SELECT 66666666,   12345,   3
    UNION ALL SELECT 77777777,   54321,   2
    UNION ALL SELECT 88888888,   54321,   2
    UNION ALL SELECT 99999999,   54321,   2
    UNION ALL SELECT 10101010,   54321,   2
    
    DELETE b
    FROM
    (
        SELECT *
            , RANK() OVER (PARTITION BY PO, NumLineItems ORDER BY LineItemID ASC) AS r
        FROM @LineItems
    ) a
    JOIN @LineItems b
        ON a.LineItemID = b.LineItemID
    WHERE r > a.NumLineItems
    
    SELECT *
    FROM @LineItems
    ORDER BY PO, LineItemID
    
        2
  •  2
  •   bwperrin    12 年前
    delete t from (select *, rank = row_number() over (partition by PO# order by lineitemid) 
                   from table ) t 
    where rank > #lineitems