Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL:如何按特定列的值“拆分”表中的行?_Sql_Sql Server_Database_Tsql_Select - Fatal编程技术网

SQL:如何按特定列的值“拆分”表中的行?

SQL:如何按特定列的值“拆分”表中的行?,sql,sql-server,database,tsql,select,Sql,Sql Server,Database,Tsql,Select,我有一个表,其中的行如下: Name | date_from | date_to | age ------+------------+------------+----- Alice | 01.12.2004 | 03.04.2008 | 35 Bob | 04.02.2013 | 04.11.2014 | 43 Name | date_from | date_to | age ------+------------+------------+----- Alice |

我有一个表,其中的行如下:

Name  | date_from  | date_to    | age
------+------------+------------+-----
Alice | 01.12.2004 | 03.04.2008 | 35
Bob   | 04.02.2013 | 04.11.2014 | 43
Name  | date_from  | date_to    | age
------+------------+------------+-----
Alice | 01.12.2004 | 01.12.2005 | 35
Alice | 01.12.2005 | 01.12.2006 | 36
Alice | 01.12.2006 | 01.12.2007 | 37
Alice | 01.12.2007 | 01.12.2008 | 38
Alice | 01.12.2008 | 03.04.2008 | 39
Bob   | 04.02.2013 | 04.02.2014 | 43
Bob   | 04.02.2014 | 04.11.2014 | 44
我想制作一个表格,将每行按 date_from和date_to列,保留名称并更新年龄,如下所示:

Name  | date_from  | date_to    | age
------+------------+------------+-----
Alice | 01.12.2004 | 03.04.2008 | 35
Bob   | 04.02.2013 | 04.11.2014 | 43
Name  | date_from  | date_to    | age
------+------------+------------+-----
Alice | 01.12.2004 | 01.12.2005 | 35
Alice | 01.12.2005 | 01.12.2006 | 36
Alice | 01.12.2006 | 01.12.2007 | 37
Alice | 01.12.2007 | 01.12.2008 | 38
Alice | 01.12.2008 | 03.04.2008 | 39
Bob   | 04.02.2013 | 04.02.2014 | 43
Bob   | 04.02.2014 | 04.11.2014 | 44

在SQL中可以做到这一点吗?

一种解决方案是生成一个数字列表,并将其与原始表连接,在开始日期加上年份,直到到达结束日期为止

下面的查询处理长达5年的时间跨度要支持更多年,您需要使用更多值扩展子查询

这是你的问题

;with cte as (
    select 1 as ctr, DATEDIFF(year, cast(date_from as datetime), cast(date_to as datetime)) as ct
        ,cast(date_from as date) as dt, cast(date_from as date) as dt2, date_to, cast(age as int) as age, [name] from test
    union all
    select ctr +  1, ct, dateadd(year, 1, dt), dt2, date_to, age + 1, [name]  from cte
    where ctr + 1 <= ct+1)
    select [name], dt as date_from, case when ctr - 1 != ct then dt else date_to end as date_to, age from cte order by dt2, age
输出:


使用SQL Server的另一种可能的解决方案

-- data preparation
    create table test1
    (
        name varchar(20),
        date_from date,
        date_to date ,
        age int

    )



    insert into test values ('alice' , '01-2-2008' , '11-3-2014' , 35 )
    insert into test values ('bob' , '06-2-2005' , '7-10-2016' , 20)

    create table test2
    (
        name varchar(20),
        date_from date,
        date_to date ,
        age int

    )
    -- query
    declare @name varchar(20)
    declare @date_from date
    declare @date_to date
    declare @age int
    declare @date_step as date
    declare @sql_st as nvarchar(max)
    declare cur cursor for select  name, date_from , date_to , age from test
    open cur;
        fetch next from cur into @name , @date_from , @date_to , @age
        while @@FETCH_STATUS = 0
        begin
            set @date_step = dateadd(year,1,@date_from)
            while @date_to > @date_step
            begin
                set @sql_st = concat('insert into test2 values (''',@name , ''' , ''' , @date_from , ''' , ''',@date_step,''',',@age , ' )')
                print(@sql_st)
                exec sp_executesql @sql_st
                set @date_from = @date_step
                set @date_step = dateadd(year,1,@date_step)
                set @age = @age + 1
            end
            set @sql_st = concat('insert into test2 values (''',@name , ''' , ''' , @date_from , ''' , ''',@date_to,''',',@age , ' )')
            exec sp_executesql @sql_st
            --print(@sql_st)            
            fetch next from cur into @name , @date_from , @date_to , @age       
        end
    close cur;
    deallocate cur;

您使用的是什么sql?MS sql、MySQL、Oracle、PostgreSQL?有一个帮助表或递归cte,可以返回所有可能的年份。JOIN.好像少了一个Alice | 01.12.2008 | 03.04.2008 | 38 Bob也一样,或者Bob第二排不应该是there@metal:您完全正确,will Correct方言不可知的答案可能很难回答,因为日期函数是高度特定于供应商的。最好使用现有的理货表,或者您可以使用…内部联接值1,2,3,4,5,6,7 xn。。。而不是union all查询。还有一个投票站在我这边。@ZoharPeled:是的,这里的值语法要短得多,我相应地更新了我的答案。谢谢