SQL生成列指定范围之间的数字
我有一张像这样的桌子SQL生成列指定范围之间的数字,sql,sql-server,oracle,Sql,Sql Server,Oracle,我有一张像这样的桌子 IDNUM | Name | LowRange | HighRange | Notes 123 | TESTS | 100 | 201 | Hello 124 | TEST2 | 200 | 210 | 125 | TESTS | 100 | 201 | Hello 我想知道是否有一个查询会返回以下结果 IDNUM | Name | Number | Notes 123 | TESTS
IDNUM | Name | LowRange | HighRange | Notes
123 | TESTS | 100 | 201 | Hello
124 | TEST2 | 200 | 210 |
125 | TESTS | 100 | 201 | Hello
我想知道是否有一个查询会返回以下结果
IDNUM | Name | Number | Notes
123 | TESTS | 100 | Hello
123 | TESTS | 101 | Hello
123 | TESTS | 102 | Hello
123 | TESTS | 103 | Hello
......til 201
124 | TEST2 | 200 |
124 | TEST2 | 201 |
124 | TEST2 | 202 |
......til 210
我正在寻找一种在SQL server 2016和Oracle 11g中都能做到这一点的方法,但任何一种方法的帮助都将不胜感激最简单的方法是数字表。以下内容在Oracle和SQL Server中都适用-假设数字的基表足够大:
with numbers as (
select row_number() over (order by idnum) - 1 as n
from t
)
select idnum, name, lowrange + n.n as number, notes
from t join
numbers n
on lowrange + n.n <= highrange;
如果上面生成的数字不够,您可以在CTE中使用交叉连接来获得更多
每个数据库都有生成数字的可选方法,但这在两个数据库中都有效。最简单的方法是数字表。以下内容在Oracle和SQL Server中都适用-假设数字的基表足够大:
with numbers as (
select row_number() over (order by idnum) - 1 as n
from t
)
select idnum, name, lowrange + n.n as number, notes
from t join
numbers n
on lowrange + n.n <= highrange;
如果上面生成的数字不够,您可以在CTE中使用交叉连接来获得更多
每个数据库都有生成数字的替代方法,但这在两个数据库中都有效。一种方法是使用中的代码并使用以下代码:
DECLARE @startnum INT
DECLARE @endnum INT
SELECT @startnum = MIN(LowRange) ,
@endnum = MAX(HighRange)
FROM IDsAndRanges
;
WITH gen AS (
SELECT @startnum AS num
UNION ALL
SELECT num+1 FROM gen WHERE num+1<=@endnum
)
SELECT *
FROM [IDsAndRanges] I
LEFT
JOIN gen G
ON G.num BETWEEN I.LowRange AND I.HighRange
option (maxrecursion 10000)
一种方法是在中使用代码并使用以下内容:
DECLARE @startnum INT
DECLARE @endnum INT
SELECT @startnum = MIN(LowRange) ,
@endnum = MAX(HighRange)
FROM IDsAndRanges
;
WITH gen AS (
SELECT @startnum AS num
UNION ALL
SELECT num+1 FROM gen WHERE num+1<=@endnum
)
SELECT *
FROM [IDsAndRanges] I
LEFT
JOIN gen G
ON G.num BETWEEN I.LowRange AND I.HighRange
option (maxrecursion 10000)
您可以将其作为递归with子句(也称为recursive CTE)来执行,如下所示:
WITH main_data (idnum, NAME, NUM, highrange, notes) AS (SELECT idnum,
NAME,
lowrange NUM,
highrange,
notes
FROM sample_data
UNION ALL
SELECT idnum,
NAME,
NUM + 1 NUM,
highrange,
notes
FROM main_data
WHERE NUM < highrange)
SELECT idnum,
NAME,
NUM,
notes
FROM main_data
ORDER BY idnum, NUM;
IDNUM NAME NUM NOTES
---------- ----- ---------- -----
123 TESTS 100 Hello
123 TESTS 101 Hello
123 TESTS 102 Hello
123 TESTS 103 Hello
124 TEST2 200
124 TEST2 201
124 TEST2 202
124 TEST2 203
124 TEST2 204
125 TESTS 150 Hello
125 TESTS 151 Hello
125 TESTS 152 Hello
125 TESTS 153 Hello
125 TESTS 154 Hello
125 TESTS 155 Hello
125 TESTS 156 Hello
125 TESTS 157 Hello
125 TESTS 158 Hello
125 TESTS 159 Hello
125 TESTS 160 Hello
您可以将其作为递归with子句(也称为recursive CTE)来执行,如下所示:
WITH main_data (idnum, NAME, NUM, highrange, notes) AS (SELECT idnum,
NAME,
lowrange NUM,
highrange,
notes
FROM sample_data
UNION ALL
SELECT idnum,
NAME,
NUM + 1 NUM,
highrange,
notes
FROM main_data
WHERE NUM < highrange)
SELECT idnum,
NAME,
NUM,
notes
FROM main_data
ORDER BY idnum, NUM;
IDNUM NAME NUM NOTES
---------- ----- ---------- -----
123 TESTS 100 Hello
123 TESTS 101 Hello
123 TESTS 102 Hello
123 TESTS 103 Hello
124 TEST2 200
124 TEST2 201
124 TEST2 202
124 TEST2 203
124 TEST2 204
125 TESTS 150 Hello
125 TESTS 151 Hello
125 TESTS 152 Hello
125 TESTS 153 Hello
125 TESTS 154 Hello
125 TESTS 155 Hello
125 TESTS 156 Hello
125 TESTS 157 Hello
125 TESTS 158 Hello
125 TESTS 159 Hello
125 TESTS 160 Hello
Oracle分层查询:
递归子查询分解子句:
Oracle分层查询:
递归子查询分解子句:
也许这不是一个好方法,但对我来说很有效
CREATE TYPE shin.tab_rows AS OBJECT (
idnum NUMBER,
description VARCHAR2(50),
num_ber NUMBER,
notes VARCHAR2(50)
);
/
CREATE TYPE shin.test_tab IS TABLE OF shin.tab_rows;
/
CREATE OR REPLACE FUNCTION shin.get_numbers
RETURN shin.test_tab PIPELINED AS
BEGIN
for records in (select IDNUM,lowrange,highrange,name,notes from shin.test_stack) LOOP
FOR num_ber IN records.lowrange..records.highrange LOOP
PIPE ROW(shin.tab_rows(records.IDNUM, records.name,num_ber,records.notes));
END LOOP;
END LOOP;
RETURN;
END;
/
select * from table(shin.get_numbers)
也许这不是一个好方法,但对我来说很有效
CREATE TYPE shin.tab_rows AS OBJECT (
idnum NUMBER,
description VARCHAR2(50),
num_ber NUMBER,
notes VARCHAR2(50)
);
/
CREATE TYPE shin.test_tab IS TABLE OF shin.tab_rows;
/
CREATE OR REPLACE FUNCTION shin.get_numbers
RETURN shin.test_tab PIPELINED AS
BEGIN
for records in (select IDNUM,lowrange,highrange,name,notes from shin.test_stack) LOOP
FOR num_ber IN records.lowrange..records.highrange LOOP
PIPE ROW(shin.tab_rows(records.IDNUM, records.name,num_ber,records.notes));
END LOOP;
END LOOP;
RETURN;
END;
/
select * from table(shin.get_numbers)
使用理货台非常简单。这在Oracle和sql server中都适用,尽管您必须以稍微不同的方式构建它。然后,从表中选择并连接到tally表,其中tally.N>=LowRange和tally.N对于数字表来说是一个很好的用法,只是列中有整数的表。连接>=下限,使用计数表非常简单。这在Oracle和sql server中都适用,尽管您必须以稍微不同的方式构建它。然后,从表中选择并连接到tally表,其中tally.N>=LowRange和tally.N对于数字表来说是一个很好的用法,只是列中有整数的表。在>=低量程和