T-SQL:需要 Top N 总是 return N 行,即使为空或空白
T-SQL: Need Top N to always return N rows, even if null or blank
T-SQL:需要前 N 行总是 return N 行,即使为空或空白
通常,命令
Select Top 5 * FROM ourTable
将 return 最多 5 行,但会更少,具体取决于这些行是否存在。
我想确保它总是 returns 5 行,(或者通常是 N 行)。
实现此目的的语法是什么?
想法是将 "FirstOrDefault" 的 LINQ 概念概括为 "First_N_OrDefault",但使用 TSQL 而不是 LINQ。
显然,'extra' 行将包含空列或空列。
这适用于使用 SSMS 14.0.17 的 Microsoft SQL Server 2014
我想使用 "TOP" 语法,如果可能的话,因此它与可能的副本不同。此外,如下所述,这可能是可以在系统中的不同层解决的问题,但如果 TSQL 也有就好了。
select top (5) c1, c2, c3 from (
select top (5) c1, c2, c3, 0 as priority from ourTable
union all
select c1, c2, c3, 1 from (values (null, null, null), (null, null, null), (null, null, null), (null, null, null), (null, null, null)) v (c1, c2, c3)
) t
order by priority
您可以使用另一个带有行的虚拟 table 来生成 table 的空行,但不匹配 JOIN
。所以你不必重复 UNION ALL
部分中的列和行:
SELECT TOP 5 * FROM (
SELECT 0 AS isDummy, * FROM table_name
-- WHERE column_name = value
UNION ALL
SELECT 1 AS isDummy, t1.* FROM table_name t1
RIGHT JOIN INFORMATION_SCHEMA.COLUMNS ON t1.id = -1000 -- not valid condition so t1 columns are empty.
) t2
ORDER BY isDummy ASC
在这种情况下,INFORMATION_SCHEMA.COLUMNS
table 用于生成额外的行。您可以选择任何其他 table 行。您可以使用 TOP N
值,直到右侧的行数 table(此处:INFORMATION_SCHEMA.COLUMNS
)。
您还可以生成包含多行的 table(就像在日历上 table):
SELECT TOP 5 * FROM (
SELECT 0 isDummy, * FROM table_name
-- WHERE column_name = value
UNION ALL
SELECT 1 isDummy, t1.* FROM table_name t1 RIGHT JOIN (
SELECT * FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) t2 ON t1.id = -1000 -- not valid condition so t1 columns are empty.
)x
ORDER BY isDummy ASC
您可以将有限的 tally table 与无缝生成的 row-number 一起使用,如下所示:
SELECT
总是一样的。唯一改变的是 mockup-table:
中的行数
DECLARE @TopCount INT=5;
--案例1:table
中多于5行
DECLARE @tbl TABLE(ID INT IDENTITY,SomeValue VARCHAR(100));
INSERT INTO @tbl VALUES
('Value1'),('Value2'),('Value3'),('Value4'),('Value5'),('Value6'),('Value7');
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--案例2:table
中少于5行
DELETE FROM @tbl WHERE ID BETWEEN 2 AND 5;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--案例三:table
中恰好一行
DELETE FROM @tbl WHERE ID <> 6;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--情况4:Table为空
DELETE FROM @tbl;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
这将从源中 return 所有 行,但至少指定的计数。
如果您想将集合限制为恰好 5 行(例如在 "Case 1" 中),您可以使用 SELECT TOP(@TopCount) *
并放置适当的 ORDER BY
。在任何情况下,这都会 return 指定的行数。
T-SQL:需要前 N 行总是 return N 行,即使为空或空白
通常,命令
Select Top 5 * FROM ourTable
将 return 最多 5 行,但会更少,具体取决于这些行是否存在。
我想确保它总是 returns 5 行,(或者通常是 N 行)。 实现此目的的语法是什么?
想法是将 "FirstOrDefault" 的 LINQ 概念概括为 "First_N_OrDefault",但使用 TSQL 而不是 LINQ。
显然,'extra' 行将包含空列或空列。
这适用于使用 SSMS 14.0.17 的 Microsoft SQL Server 2014
我想使用 "TOP" 语法,如果可能的话,因此它与可能的副本不同。此外,如下所述,这可能是可以在系统中的不同层解决的问题,但如果 TSQL 也有就好了。
select top (5) c1, c2, c3 from (
select top (5) c1, c2, c3, 0 as priority from ourTable
union all
select c1, c2, c3, 1 from (values (null, null, null), (null, null, null), (null, null, null), (null, null, null), (null, null, null)) v (c1, c2, c3)
) t
order by priority
您可以使用另一个带有行的虚拟 table 来生成 table 的空行,但不匹配 JOIN
。所以你不必重复 UNION ALL
部分中的列和行:
SELECT TOP 5 * FROM (
SELECT 0 AS isDummy, * FROM table_name
-- WHERE column_name = value
UNION ALL
SELECT 1 AS isDummy, t1.* FROM table_name t1
RIGHT JOIN INFORMATION_SCHEMA.COLUMNS ON t1.id = -1000 -- not valid condition so t1 columns are empty.
) t2
ORDER BY isDummy ASC
在这种情况下,INFORMATION_SCHEMA.COLUMNS
table 用于生成额外的行。您可以选择任何其他 table 行。您可以使用 TOP N
值,直到右侧的行数 table(此处:INFORMATION_SCHEMA.COLUMNS
)。
您还可以生成包含多行的 table(就像在日历上 table):
SELECT TOP 5 * FROM (
SELECT 0 isDummy, * FROM table_name
-- WHERE column_name = value
UNION ALL
SELECT 1 isDummy, t1.* FROM table_name t1 RIGHT JOIN (
SELECT * FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) t2 ON t1.id = -1000 -- not valid condition so t1 columns are empty.
)x
ORDER BY isDummy ASC
您可以将有限的 tally table 与无缝生成的 row-number 一起使用,如下所示:
SELECT
总是一样的。唯一改变的是 mockup-table:
DECLARE @TopCount INT=5;
--案例1:table
中多于5行DECLARE @tbl TABLE(ID INT IDENTITY,SomeValue VARCHAR(100));
INSERT INTO @tbl VALUES
('Value1'),('Value2'),('Value3'),('Value4'),('Value5'),('Value6'),('Value7');
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--案例2:table
中少于5行DELETE FROM @tbl WHERE ID BETWEEN 2 AND 5;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--案例三:table
中恰好一行DELETE FROM @tbl WHERE ID <> 6;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
--情况4:Table为空
DELETE FROM @tbl;
WITH Tally(Nmbr) AS(SELECT TOP(@TopCount) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
,NumberedRows AS(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS GeneratedRowNumber, * FROM @tbl)
SELECT *
FROM NumberedRows nr
FULL OUTER JOIN Tally t ON nr.GeneratedRowNumber=t.Nmbr;
这将从源中 return 所有 行,但至少指定的计数。
如果您想将集合限制为恰好 5 行(例如在 "Case 1" 中),您可以使用 SELECT TOP(@TopCount) *
并放置适当的 ORDER BY
。在任何情况下,这都会 return 指定的行数。