根据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
答案 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)