SQL:将具有开始/结束的行扩展为单独的行

发布于 2024-09-15 01:33:43 字数 484 浏览 9 评论 0原文

我有这样的记录:

start, end , total  
 830 , 1300,   5
 1400, 1430,   2

我想扩展到:

instance , total  
  830    ,   5
  831    ,   5
  832    ,   5
  ...
  1299   ,   5
  1300   ,   5

  1400   ,   2
  1401   ,   2
  ...
  1429   ,   2
  1430   ,   2

How can I do this using SQL in MSSQL 2005?

编辑:谢谢大家,很好的答案。有几个去上班了我只是忘了说,虽然开始/结束实际上是存储为 int 的时间,所以 0830 到 1300 应该达到 0859,然后是 0900。我不能指望你们在同一个问题中回答这个问题,我会努力的围绕它。再次感谢

I have a records like this:

start, end , total  
 830 , 1300,   5
 1400, 1430,   2

that I'd like to expand to:

instance , total  
  830    ,   5
  831    ,   5
  832    ,   5
  ...
  1299   ,   5
  1300   ,   5

  1400   ,   2
  1401   ,   2
  ...
  1429   ,   2
  1430   ,   2

How can I do this using SQL in MSSQL 2005?

EDIT: thanks everyone, great answers. Got a few to work. I just forgot to say though that the start/end was really a time stored as an int, so 0830 to 1300 should go upto 0859 then 0900. I can't expect you guys to answer that in this same question, i'll work around it. Thanks again

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不喜欢何必死缠烂打 2024-09-22 01:33:44

使用 CTE:(

with number_cte(n) as 
 (select n from (select 0 n) m union all select n+1 n
  from number_cte where n< 2400)
select start+n instance, total
from 
datatable
join number_cte on start+n between start and [end]
where start+n - 100*floor((start+n)/100) between 0 and 59
order by 1
option (maxrecursion 2401)

如果需要大于 2400 的范围,则适当增加 n<...和 ​​maxrecursion 数字。)

进行编辑以防止包含无效实例(即结束于 60 到 99 之间的时间值)值。

Using a CTE:

with number_cte(n) as 
 (select n from (select 0 n) m union all select n+1 n
  from number_cte where n< 2400)
select start+n instance, total
from 
datatable
join number_cte on start+n between start and [end]
where start+n - 100*floor((start+n)/100) between 0 and 59
order by 1
option (maxrecursion 2401)

(Increase n< ... and maxrecursion numbers as appropriate, if ranges greater than 2400 are required.)

Edited to prevent non-valid Instance (ie. time values ending between 60 and 99) values being included.

吃素的狼 2024-09-22 01:33:44

这应该可以解决问题:

create table input (start int, [end] int, total int)

insert input values (830, 1300, 5)
insert input values (1400, 1430, 2)

declare @output table (instance int, start int, [end] int, total int)

insert @output select start, start, [end], total from input

while @@rowcount > 0
    insert @output
    select
        max(instance) + 1,
        start,
        [end],
        total
    from @output
    group by
        start,
        [end],
        total
    having max(instance) < [end]

select instance, total from @output order by instance

这会输出与问题中描述的相同(未截断)的结果。

可能有一些奇特的 CTE 方法,但我认为这行不通,因为你需要无限量的递归。

This should do the trick:

create table input (start int, [end] int, total int)

insert input values (830, 1300, 5)
insert input values (1400, 1430, 2)

declare @output table (instance int, start int, [end] int, total int)

insert @output select start, start, [end], total from input

while @@rowcount > 0
    insert @output
    select
        max(instance) + 1,
        start,
        [end],
        total
    from @output
    group by
        start,
        [end],
        total
    having max(instance) < [end]

select instance, total from @output order by instance

This outputs the same (untruncated) results as you described in the question.

There might be some fancy CTE approach but I don't think that could work since you'd need an indefinite amount of recursion.

拔了角的鹿 2024-09-22 01:33:44

假设您的 END 值有一个有限的最大值,您可以使用数字表(更改 2000 I 曾经是您的最大 END 值):

declare @Test table (
    start int,
    [end] int,
    total int
)

insert into @Test
    (start, [end], total)
    select 830, 1300, 5
    union
    select 1400, 1430, 2

;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 2000
)
select n.n, t.total
    from @Test t
        cross join Nbrs n
    where n.n between t.start and t.[end]
    option (MAXRECURSION 2000)

Assuming there is a finite max to your END values, you can use a numbers table (change the 2000 I used to be your max END value):

declare @Test table (
    start int,
    [end] int,
    total int
)

insert into @Test
    (start, [end], total)
    select 830, 1300, 5
    union
    select 1400, 1430, 2

;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 2000
)
select n.n, t.total
    from @Test t
        cross join Nbrs n
    where n.n between t.start and t.[end]
    option (MAXRECURSION 2000)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文