我有一个独特的要求,以10的倍数返回结果行数。例如,如果实际数据行为3,我必须添加另外7个空行以使其成为10.如果实际数据行为16,我必须添加另外4个空白行使其成为20,依此类推。
不使用过程,是否可以使用SELECT语句实现此目的? 空行可以只包含NULL值或空格或零。
您可以假设对数据行进行任何简单查询;目标是了解如何以10的倍数动态返回行。
示例:
Select EmpName FROM Employees
如果有3名员工,我仍然应该返回10行,其余7行包含NULL值或空白。
我正在使用SQL Server 2012。
答案 0 :(得分:2)
这是一个非常原始的想法如何实现:
WITH data(r) AS (
SELECT 1 r FROM dual
UNION ALL
SELECT r+1 r FROM data WHERE r < 10
)
SELECT sd.*
FROM data d
left join some_data sd on d.r = sd.id
这是双表结构:
create table dual (dummy varchar(1));
insert into dual values ('x');
小提琴:http://sqlfiddle.com/#!6/5ffcc/4
其中一个可能的选择是:
WITH data(r) AS (
SELECT 1 r FROM dual
UNION ALL
SELECT r+1 r FROM data WHERE r < 10
)
SELECT sd.*
FROM
(select r, row_number() over (order by r) rn from data) d
left join (
select id, name, row_number() over (order by id) rn from some_data sd
) sd
on d.rn = sd.rn
这种颜色的明显缺点:
但也许它会帮助你找到更好的解决方案。
答案 1 :(得分:1)
这是处理它的另一种相当简单的方法......
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
EmpID INT NOT NULL,
EmpName VARCHAR(20) NOT NULL
);
INSERT #TestData(EmpID, EmpName) VALUES
(47, 'Bob'),(33, 'Mary'), (88, 'Sue');
-- data as it exists...
SELECT
td.EmpID,
td.EmpName
FROM
#TestData td;
-- the desired output...
WITH
cte_AddRN AS (
SELECT
td.EmpID,
td.EmpName,
RN = ROW_NUMBER() OVER (ORDER BY td.EmpName)
FROM
#TestData td
),
cte_TenRows AS (
SELECT n.RN FROM ( VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10) ) n (RN)
)
SELECT
ar.EmpID,
ar.EmpName
FROM
cte_TenRows tr
LEFT JOIN cte_AddRN ar
ON tr.RN = ar.RN
ORDER BY
tr.RN;
结果...
-- data as it exists...
EmpID EmpName
----------- --------------------
47 Bob
33 Mary
88 Sue
-- the desired output...
EmpID EmpName
----------- --------------------
47 Bob
33 Mary
88 Sue
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
答案 2 :(得分:0)
根据以上2个答案,我就是这样做的:
WITH DATA AS
(SELECT EmpName FROM Employees),
DataSummary AS
(SELECT COUNT(*) AS NumDataRows FROM DATA),
ReqdDataRows AS
(SELECT CEILING(NumDataRows/10.0)*10 AS NumRowsReqd FROM DataSummary),
FillerRows AS
(
SELECT 1 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 2 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 3 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 4 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 5 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 6 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 7 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 8 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 9 AS SLNO, '00000' AS FillerCol
UNION ALL
SELECT 10 AS SLNO, '00000' AS FillerCol
)
SELECT * FROM DATA
--UNION ALL
--SELECT CONVERT(VARCHAR(10), NumDataRows) FROM DataSummary
--UNION ALL
--SELECT CONVERT(VARCHAR(10), NumRowsReqd) FROM ReqdDataRows
UNION ALL
SELECT FillerCol FROM FillerRows
WHERE (SELECT NumDataRows FROM DataSummary) + SLNO <= (SELECT NumRowsReqd FROM ReqdDataRows)
这给了我想要的输出。这样可以避免使用ROW_NUMBER
和ORDER
。可以使用SELECT * FROM (VALUES...)
进一步简化表FillerRows,并且可以将第2和第3个表DataSummary
和ReqdDataRows
合并到单个SELECT语句中。
这种方法是一步一步的方法,易于理解和调试,如:
欢迎任何有关进一步简化此事的建议。