根据sql server中的记录计数将记录拆分为3列

时间:2017-09-05 06:56:54

标签: sql sql-server sql-server-2012

根据sql server中的记录计数将记录拆分为3列

我正在尝试从查询中选择记录。我有3列来显示记录 我根据计数拆分了记录,这就是我需要将记录分成10行 每个部分。

此外,在我有超过30条记录的事件中,它需要显示第1列中的记录

请参阅下面的截图。

Reg  SNO   Reg  SNO   Reg   SNO 
1           11         21
2           12         22
3                 

10          20         30

Reg  SNO   Reg  SNO   Reg   SNO 
31          41         51
32          42         52
33                 

40          50         60

记录应该与excel表中给出的相同。

我已经在存储过程中尝试了下面的查询。但是看起来我失去了Joins中的一些逻辑和偶数条件中我给出的奇数函数。如果记录数大于30,它就没有像我预期的那样检索。 任何帮助都会非常感激。

CREATE PROC  MYTEST
AS  
IF OBJECT_ID('tempdb..#test1') IS NOT NULL
    DROP TABLE #test1

IF OBJECT_ID('tempdb..#test2') IS NOT NULL
    DROP TABLE #test2 

IF OBJECT_ID('tempdb..#test3') IS NOT NULL
    DROP TABLE #test3


SELECT  ROW_NUMBER() OVER ( ORDER BY rno ) 'rno' ,
        Reg ,
        SerialNo
INTO    #test1
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY EmployeeId ) 'rno' ,
                    Reg ,
                    SerialNo
          FROM      tRe
        ) AS c
WHERE   ( rno % \10 > 0
          AND ( rno / 10 ) % 3 = 0
        )
        OR ( rno % 10 = 0
             AND ( rno / 10 ) % 3 = 1
           )

SELECT  ROW_NUMBER() OVER ( ORDER BY rno ) 'rno1' ,
        Reg AS Reg1 ,
        SerialNo AS SerialNo1
INTO    #test2
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY EmployeeId ) 'rno' ,
                    Reg ,
                    SerialNo
          FROM      tRe
        ) AS c
WHERE   ( rno % 10 > 0
          AND ( rno / 10 ) % 3 = 1
        )
        OR ( rno % 10 = 0
             AND ( rno / 10 ) % 3 = 0
           )

SELECT  ROW_NUMBER() OVER ( ORDER BY rno ) 'rno2' ,
        Reg AS Reg2 ,
        SerialNo AS SerialNo2
INTO    #test3
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY EmployeeId ) 'rno' ,
                    Reg ,
                    SerialNo
          FROM      tRe
        ) AS c
WHERE   ( rno % \10 > 0
          AND ( rno / 10 ) % 3 = 0
        )
        OR ( rno % 10 = 0
             AND ( rno / 10 ) % 3 = 1
           )


SELECT  *
FROM    #test1 a
        FULL OUTER JOIN #test2 b ON a.rno = b.rno1
FULL  outer join #test3 c on b.rno1=c.rno2


EXEC MYTEST

2 个答案:

答案 0 :(得分:1)

以下内容将数据拆分为30行的页面,然后将每页拆分为3列10 ...

编辑:已更新,以包含NVARCHAR数据类型列。

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    ItemNo INT NOT NULL PRIMARY KEY CLUSTERED,
    SomeString NVARCHAR(15) NOT NULL 
    );
INSERT #TestData (ItemNo, SomeString)
SELECT TOP 1000
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
    CAST(ao.object_id AS NVARCHAR(15))
FROM
    sys.all_objects ao;

--  SELECT * FROM #TestData td;

--==============================================

WITH 
    cte_PageCol AS (
        SELECT 
            td.ItemNo,
            PageNum = DENSE_RANK() OVER (PARTITION BY m30.Mod30 ORDER BY td.ItemNo),
            ColumnNum = DENSE_RANK() OVER (PARTITION BY m10.Mod10 ORDER BY m30.Mod30),
            td.SomeString
        FROM
            #TestData td
            CROSS APPLY ( VALUES (ISNULL(NULLIF(td.ItemNo % 30, 0), 30)) ) m30 (Mod30)
            CROSS APPLY ( VALUES (ISNULL(NULLIF(m30.Mod30 % 10, 0), 10)) ) m10 (Mod10)
        ),
    cte_AddRN AS (
        SELECT 
            pc.ItemNo, pc.PageNum, pc.ColumnNum, pc.SomeString,
            RN = ROW_NUMBER() OVER (PARTITION BY pc.PageNum, pc.ColumnNum ORDER BY pc.ItemNo)
        FROM
            cte_PageCol pc
        )
SELECT 
    ar.PageNum,
    Col1 = MAX(CASE WHEN ar.ColumnNum = 1 THEN ar.ItemNo END),
    Col1_Val = MAX(CASE WHEN ar.ColumnNum = 1 THEN ar.SomeString END),
    Col2 = MAX(CASE WHEN ar.ColumnNum = 2 THEN ar.ItemNo END),
    Col2_Val = MAX(CASE WHEN ar.ColumnNum = 2 THEN ar.SomeString END),
    Col3 = MAX(CASE WHEN ar.ColumnNum = 3 THEN ar.ItemNo END),
    Col3_Val = MAX(CASE WHEN ar.ColumnNum = 3 THEN ar.SomeString END)
FROM
    cte_AddRN ar
GROUP BY 
    ar.PageNum,
    ar.RN
ORDER BY 
    ar.PageNum,
    ar.RN;

结果样本......

PageNum              Col1        Col1_Val        Col2        Col2_Val        Col3        Col3_Val
-------------------- ----------- --------------- ----------- --------------- ----------- ---------------
1                    1           2121987014      11          1595261016      21          1832241610
1                    2           1140411510      12          1403260332      22          1848639041
1                    3           934103092       13          1355260161      23          464516666
1                    4           1751830240      14          1419260389      24          435497504
1                    5           111799388       15          1451260503      25          448516609
1                    6           1671069267      16          1435260446      26          1090523542
1                    7           1819977838      17          1371260218      27          1635970274
1                    8           1611261073      18          358244459       28          127004803
1                    9           1643261187      19          1867925954      29          786990954
1                    10          1627261130      20          1851925897      30          432516552
2                    31          1474524910      41          1002746925      51          1748617718
2                    32          1643157077      42          841162320       52          1860618117
2                    33          1675157191      43          873162434       53          980462995

答案 1 :(得分:0)

试试这个,脚本中的评论。

IF OBJECT_ID('tempdb..#tre') is not null drop table #tre
;WITH tre
AS
(
    SELECT
        ABS(CHECKSUM(NEWID())) % 10000 Reg
        , ABS(CHECKSUM(NEWID())) % 10000 + 20000 SerialNo
        , ABS(CHECKSUM(NEWID())) % 10000 + 50000 EmployeeID
        , 1 AS ID

    UNION ALL

    SELECT
        ABS(CHECKSUM(NEWID())) % 10000
        , ABS(CHECKSUM(NEWID())) % 10000 + 20000
        , ABS(CHECKSUM(NEWID())) % 10000 + 50000 EmployeeID
        , ID + 1
    FROM tre    
    WHERE ID < 1000
)
SELECT
    *
INTO #tre
FROM tre
OPTION (MAXRECURSION 1002) 


-- Create Employee table with row numbers
IF OBJECT_ID('tempdb..#Emps') IS NOT NULL DROP TABLE #Emps
SELECT    
    ROW_NUMBER() OVER ( ORDER BY EmployeeId ) 'rno'
    , Reg
    , SerialNo
INTO #Emps
FROM #tRe

CREATE CLUSTERED INDEX CIX_tempEmps_rno ON #Emps (rno)

DECLARE @NumberOfItemLines INT = 10
;WITH innerTally -- Create your numbers to fill up your first page i.e. 1 - 30
AS
(
    SELECT 1 AS ID
    UNION ALL
    SELECT ID + 1
    FROM innerTally
    WHERE ID < 3
),
outerTally
AS
(
    -- Split your rows from previous table into three columns
    SELECT
        a.ID as Col1
        , b.ID as Col2
        , c.ID as Col3
    FROM innerTally a
    JOIN innerTally b
        ON b.ID = a.ID + 1
    JOIN innerTally c
        ON c.ID = a.ID + 2
    WHERE a.ID = 1

    UNION ALL

    -- Create additional pages
    SELECT 
        Col1 + 3
        , Col2 + 3
        , Col3 + 3
    FROM OuterTally
    WHERE Col1 < 3*(@NumberOfItemLines -1)-1 -- Arbitrary limiter, just keep it as big as or bigger than you require
)
-- Join your table 3 times for each set of column ID's
SELECT
    e1.rno
    , e1.Reg
    , e1.SerialNo
    , e2.rno
    , e2.Reg
    , e2.SerialNo
    , e3.rno
    , e3.Reg
    , e3.SerialNo 
FROM OuterTally t
JOIN #Emps e1
    ON e1.rno = t.Col1
JOIN #Emps e2
    ON e2.rno = t.Col2
JOIN #Emps e3
    ON e3.rno = t.Col3
ORDER BY 1
OPTION (MAXRECURSION 1000)