在SQL Server 2012

时间:2017-10-22 06:03:12

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

我有一个独特的要求,以10的倍数返回结果行数。例如,如果实际数据行为3,我必须添加另外7个空行以使其成为10.如果实际数据行为16,我必须添加另外4个空白行使其成为20,依此类推。

不使用过程,是否可以使用SELECT语句实现此目的? 空行可以只包含NULL值或空格或零。

您可以假设对数据行进行任何简单查询;目标是了解如何以10的倍数动态返回行。

示例:

Select EmpName FROM Employees

如果有3名员工,我仍然应该返回10行,其余7行包含NULL值或空白。

我正在使用SQL Server 2012。

3 个答案:

答案 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 

这种颜色的明显缺点:

  • &#39; R&#39;价值生成规则很可能不是那么简单 案件。
  • 查询执行前必须知道行数。

但也许它会帮助你找到更好的解决方案。

答案 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_NUMBERORDER。可以使用SELECT * FROM (VALUES...)进一步简化表FillerRows,并且可以将第2和第3个表DataSummaryReqdDataRows合并到单个SELECT语句中。

这种方法是一步一步的方法,易于理解和调试,如:

  1. 获取实际数据行
  2. 获取数据行数
  3. 计算所需的号码。数据行
  4. UNION带有填充行的实际数据行
  5. 欢迎任何有关进一步简化此事的建议。