我正在寻找一个查询来获得以下输出:
Id Number
-- ------
1 241100
2 241110
2 241111
2 241112
2 241113
2 241114
2 241115
表格结构:
Id Number From To
-- ------ ---- ----
1 241100 NULL NULL
2 241110 111 115
没有from / to范围的行必须返回该数字。其他人必须返回后跟SUBSTRING(Number, 1, 3) + <from/to range>
一种可能的解决方案是使用while循环。但那不是我喜欢的方式。它很慢。而且无法改变数据结构。我们从第三方供应商处查询数据。
在应用程序网站上,我有一个(非常小的)数字列表,例如'241113','241000',......并且需要知道该号码被分配给哪个ID。
我将用于获得结果的查询是:
SELECT Id, Number FROM MyView WHERE Number IN ('241113', '241000')
答案 0 :(得分:4)
你可以create an auxiliary numbers table
CREATE TABLE Numbers
(
N int primary key
)
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
INSERT INTO Numbers
SELECT N FROM cteTally
WHERE N <= 1000000;
然后生成您想要的结果
;WITH T (Id, Number, [From], [To]) AS
(
SELECT 1, 241100, NULL, NULL UNION ALL
SELECT 2, 241110, 111, 115
)
SELECT Id, Number + N-1 AS Number
FROM T
JOIN Numbers ON N <= 1 + ISNULL(1 + [To] - [From],0)
答案 1 :(得分:3)
我将用于获得结果的查询是:
SELECT Id,Number FROM MyView WHERE Number IN('241113','241000')
这是您可以编写该查询的方式。无需生成数字。
declare @T table
(
Id int,
Number int,
[From] int,
[To] int
)
insert into @T values
(1, 241100, NULL, NULL),
(2, 241110, 111, 115)
select T.Id, V.Number
from @T as T
inner join (values (241113),
(241100)) as V(Number)
on V.Number between T.Number and T.Number + isnull(T.[To], 0)
将您查找的数字放在表变量中的版本。
declare @V table(Number int)
insert into @V values(241100)
insert into @V values(241113)
select T.Id, V.Number
from @T as T
inner join @V as V
on V.Number between T.Number and T.Number + isnull(T.[To], 0)
我没有在任何地方使用From
因为我不清楚除了null
和number+1
之外的那个列中可能的值。
在过滤出数字之前生成数字的版本。结果是一样的,我相信表现不太好。
;with C as
(
select T.Id,
T.Number
from @T as T
union all
select T.Id,
C.Number + 1
from @T as T
inner join C
on C.Id = T.Id
where stuff(C.Number, 1, 3, '') < T.[To]
)
select Id, Number
from C
where Number in ('241113', '241100')
答案 2 :(得分:0)
我知道你正在使用tsql,但出于好奇,我想知道如何在pgsql中解决一个解决方案:
create schema arrays;
set search_path = 'arrays';
create table ranges
(
"Id" bigint primary key,
"Number" int not null,
"From" int,
"To" int
);
insert into ranges("Id", "Number", "From", "To") values
(1, 241100, null, null),
(2, 241110, 111, 115),
(3, 2411200, 1281, 1293);
create view ranges_gen as
select
"Id",
(row_number() over(partition by "Id") - 1 + "Bottom") as "Number"
from
(
select
"Id",
coalesce(round("Number", -length("From"::text)) + "From", "Number") as "Bottom",
unnest(array_fill(0, array[coalesce("To" - "From" + 1, 1)]))
from ranges
) as ranges_duped;
select * from ranges_gen;