首页 文章

SQL Server每5行循环一次表

提问于
浏览
0

我需要编写一个存储过程或表函数来返回一个新的数据表作为新的数据源 . 我希望在发票ID列的基础上每5行循环一次原始表(它可能不是从1开始),前5行添加到新表的左侧,后5行添加到新表的右侧新表,左边第3行,依此类推 .

例如,这是原始表:

这是期望表:

提前致谢!

6 回答

  • 0

    看起来好像要将表拆分为2个表,交替5行 . 一个简单的方法是:

    • 将数据带入具有额外列的临时表(比如grouping_id)

    • 更新分组ID,以便每5行具有相同的ID . 您可以使用 in_invoiceId % 5 (nod函数) . 在此步骤之后,前5行将具有grouping_id 0,接下来的5将具有1,接下来将具有2(假设您的发票ID对于所有行递增1) .

    • 你可以用奇数和偶数grouping_id的where子句进行正常选择

  • 0
    declare @rowCount int = 5;
    with cte as (
        select *,( (IN_InvoiceID-1) / @rowCount ) % 2 group1
            ,( (IN_InvoiceID-1) / @rowCount ) group2
            ,IN_InvoiceID % @rowCount group3
        from T 
    )
    select * from cte
    select T1.INID,T1.IN_InvoiceID,T1.IN_InvoiceAmount,T2.INID,T2.IN_InvoiceID,T2.IN_InvoiceAmount
    from CTE  T1
    left join CTE T2 on T2.group1 = 1 and T1.group2 = T2.group2-1 and T1.group3 = T2.group3
    where T1.group1 = 0
    

    测试DDL

    CREATE TABLE T
        ([INID] varchar(38), [IN_InvoiceID] int, [IN_InvoiceAmount] int)
    ;
    
    INSERT INTO T
        ([INID], [IN_InvoiceID], [IN_InvoiceAmount])
    VALUES
        ('DB3E17E6-35C5-41:121-93B1-F809BF6B2972', 1, 2999),
        ('3212F048-8213-4FCC-AB64-121485B77D4E43', 2, 3737),
        ('E3526373-A204-40F5-801C-7F8302A4E5E2', 3, 3175),
        ('76CC9C19-BF79-4E8A-8034-A33805AD3390', 4, 391),
        ('EC7A2FBC-B62D-4865-88DE-A8097975F125', 5, 1206),
        ('52AD3046-21331-4F0A-BD1D-67F232C54244', 6, 402),
        ('CA48F132-A9F5-4516-9E58-CDEE6644AAD1', 7, 1996),
        ('02E10C31-CAB2-4220-B66A-CEE5E67A9378', 8, 3906),
        ('98F1EEFF-B07A-4B65-87F4-E165264284DD', 9, 2575),
        ('91EBDD8B-B73C-470C-8900-DD66078483DB', 10, 2965),
        ('6E2490E5-C4DE-4833-877F-1590F7BDC1B8', 11, 1603),
        ('00985921-AC3C-4E3E-BAE1-7F58302F831A', 12, 1302)
    ;
    

    结果:

    2018-12-10.16.19.53-image.png

  • 0

    您能否查看文章Display Data in Multiple Columns using SQL以示例情况显示数据库开发人员如何使用Row_Number()函数和模式算术表达式以列式模式显示数据行列表

    您需要从示例中不同的行添加其他列

  • 0

    理想情况下,您可以使用2个表主表和详细信息表进行管理 .

    但由于我的好奇心,我能够解决并给出答案

    Declare @table table(id int identity, invoice_id int)
    
    ; WITH Numbers AS
    (
        SELECT n = 1
        UNION ALL
        SELECT n + 1
        FROM Numbers
        WHERE n+1 <= 50
    )
    
    
    insert into @table  SELECT n
    FROM Numbers
    
    Select (a.id  )%5 ,* from @table a join @table b on a.id+5 = b.id and a.id != b.id
    
    ;WITH Numbers AS
    (
        SELECT n = 1, o = 5
        UNION ALL
        SELECT n + 10, o = o+10
        FROM Numbers
        WHERE n+1 <= 50
    )
    
    select a.id ParentId,a.invoice_id ParentInvoiceId, --b.n, b.o, 
    c.invoice_id childInvoiceID from @table a 
    join Numbers b on a.id between b.n and b.o
    left join @table c on a.id + 5 = c.id
    
  • 0

    这是我的解决方案

    首先,我根据in_invoiceid是否可以被5整除来创建grps . (忽略余数)

    之后,我创建一个类别来指示备选组之间(即通过检查余数是否为0或其他)

    然后,它是基于in_invoiceid排序的类别字段密集查找记录的问题

    最后是category = 1行的连接,具有与category = 0中的记录相同的dense_rank

    create table Invoicetable(IN_ID varchar(100), IN_InvoiceID int)
    
    
    INSERT INTO Invoicetable (IN_ID, IN_InvoiceID)
    VALUES
        ('2345-BCDE-6645-1DDF', 1),
        ('2345-BCDE-6645-3DDF', 2),
        ('2345-BCDE-6645-4DDF', 3),
        ('2345-BCDE-6645-5DDF', 4),
        ('2345-BCDE-6645-6DDF', 5),
        ('2345-BCDE-6645-7DDF', 6),
        ('2345-BCDE-6645-aDDF', 7),
        ('2345-BCDE-6645-sDDF', 8),
        ('2345-BCDE-6645-dDDF', 9),
        ('2345-BCDE-6645-dDDF', 10),
        ('2345-BCDE-6645-dDDF', 11),
        ('2345-BCDE-6645-dDDF', 12);
    
    with data
      as (
    select *
          ,(in_invoiceid-1)/5 as grp
          ,case when ((in_invoiceid-1)/5)%2=0 then '1' else '0' end as category
          ,dense_rank() over(partition by  case when ((in_invoiceid-1)/5)%2=0 then '1' else '0' end
                        order by in_invoiceid) as rnk
      from invoicetable a
          )
       select *
          from data a
     left join data b
            on a.rnk=b.rnk       
           and b.category=0
         where a.category=1
    

    这是db fiddle链接 .

    https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=287f101737c580ca271940764b2536ae

  • 0

    您可以尝试使用以下方法 . 使用 (((ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) - 1) / 5) % 2 = 0) 对表进行除法,该组将记录分组在左侧和右侧组中 .

    CREATE TABLE #InvoiceTable(
        IN_ID varchar(24),
        IN_InvoiceID int
    )
    
    
    INSERT INTO #InvoiceTable (IN_ID, IN_InvoiceID)
    VALUES
        ('2345-BCDE-6645-1DDF', 1),
        ('2345-BCDE-6645-3DDF', 2),
        ('2345-BCDE-6645-4DDF', 3),
        ('2345-BCDE-6645-5DDF', 4),
        ('2345-BCDE-6645-6DDF', 5),
        ('2345-BCDE-6645-7DDF', 6),
        ('2345-BCDE-6645-aDDF', 7),
        ('2345-BCDE-6645-sDDF', 8),
        ('2345-BCDE-6645-dDDF', 9),
        ('2345-BCDE-6645-dDDF', 10),
        ('2345-BCDE-6645-dDDF', 11),
        ('2345-BCDE-6645-dDDF', 12);
    
    WITH cte AS (
        SELECT 
            IN_ID, 
            IN_InvoiceID, 
            CASE
                WHEN (((ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) - 1) / 5) % 2 = 0) THEN 'L'
                ELSE 'R'
            END AS IN_Position
        FROM #InvoiceTable
    ),
    cteL AS (
        SELECT IN_ID, IN_InvoiceID, ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) AS IN_RowNumber
        FROM cte
        WHERE IN_Position = 'L'
    ),
    cteR AS (
        SELECT IN_ID, IN_InvoiceID, ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) AS IN_RowNumber
        FROM cte
        WHERE IN_Position = 'R'
    )
    
    SELECT cteL.IN_ID, cteL.IN_InvoiceID, cteR.IN_ID, cteR.IN_InvoiceID
    FROM cteL
    LEFT JOIN cteR ON (cteL.IN_RowNumber = cteR.IN_RowNumber)
    

    输出:

    IN_ID               IN_InvoiceID    IN_ID               IN_InvoiceID
    2345-BCDE-6645-1DDF 1               2345-BCDE-6645-7DDF 6
    2345-BCDE-6645-3DDF 2               2345-BCDE-6645-aDDF 7
    2345-BCDE-6645-4DDF 3               2345-BCDE-6645-sDDF 8
    2345-BCDE-6645-5DDF 4               2345-BCDE-6645-dDDF 9
    2345-BCDE-6645-6DDF 5               2345-BCDE-6645-dDDF 10
    2345-BCDE-6645-dDDF 11              NULL                NULL
    2345-BCDE-6645-dDDF 12              NULL                NULL
    

相关问题