Tsql 将具有一个DateTime列的行对合并为具有开始和结束日期列的单行

Tsql 将具有一个DateTime列的行对合并为具有开始和结束日期列的单行,tsql,Tsql,编辑:关于一个名称可以有多对不重叠的开始和结束这一事实,非常需要澄清。因此,合并对可以标识为“运行” 我猜这是一个重复的问题,但我似乎找不到另一个。如果有人能指给我看,那么这个可以被关闭或删除,或者别的什么 我有一张这样的桌子: Id Name Action ActionDate ---- ------- ------ ---------- 1 John Start 01/15/2013 2 Mary Start

编辑:关于一个名称可以有多对不重叠的开始和结束这一事实,非常需要澄清。因此,合并对可以标识为“运行”

我猜这是一个重复的问题,但我似乎找不到另一个。如果有人能指给我看,那么这个可以被关闭或删除,或者别的什么

我有一张这样的桌子:


Id   Name      Action      ActionDate
---- -------   ------      ----------
1    John      Start       01/15/2013
2    Mary      Start       01/17/2013
3    Nancy     Start       01/17/2013
4    John      End         01/18/2013
5    Mary      End         01/18/2013
6    Nancy     End         01/20/2013
7    John      Start       01/19/2013
8    Mary      Start       01/20/2013
9    Nancy     Start       01/25/2013
10   John      End         01/21/2013
11   Mary      End         01/22/2013
12   Nancy     End         01/30/2013
我需要一个使用基于集合的查询的结果集,如下所示:


Id   Name    Run   StartActionDate    EndActionDate
---- ------- ----  ---------------    -------------
1    John    1     01/15/2013         01/18/2013
2    John    2     01/19/2013         01/21/2013
3    Mary    1     01/17/2013         01/18/2013
4    Mary    2     01/20/2013         01/22/2013
5    Nancy   1     01/17/2013         01/20/2013
6    Nancy   2     01/25/2013         01/30/2013
看看这个

select MIN(Id),Name,MIN(case Action when 'Start' then ActionDate End) as StartActionDate,MIN(case Action When 'End' then ActionDate End) as EndActiondate from dbo.Table group by Name

假设每个名称只有一条带“开始”的记录和一条带“结束”的记录,类似这样的方法应该可以工作:

SELECT T1.Id, T1.Name, T1.ActionDate AS [StartActionDate], T2.ActionDate AS [EndActionDate]
FROM MyTable T1
INNER JOIN MyTable T2 ON T1.Name = T2.Name
WHERE T1.Action = 'Start' AND T2.Action = 'End'

如果每个
名称都有多对
名称,则不清楚要返回什么
id
,但您应该能够使用类似
row\u number()
的窗口函数为每个名称生成一个唯一的序列,然后生成最终结果:

;with cte as
(
  select id, name, action, actiondate,
    row_number() over(partition by name, action
                      order by actiondate) seq
  from yourtable
)
select 
  min(id) id,
  name,
  max(case when action = 'start' then actiondate end) StartActionDate,
  max(case when action = 'end' then actiondate end) EndActionDate
from cte
group by name, seq
order by id;

根据您的数据更改,您应该能够使用类似于:

;with cte as
(
  select id, name, action, actiondate,
    row_number() over(partition by name, action
                      order by actiondate) seq
  from yourtable
)
select 
  row_number() over(order by name) id,
  name,
  seq run,
  max(case when action = 'start' then actiondate end) StartActionDate,
  max(case when action = 'end' then actiondate end) EndActionDate
from cte
group by name, seq
order by id
看。这就产生了一个结果:

| ID |  NAME | RUN |                STARTACTIONDATE |                  ENDACTIONDATE |
|----|-------|-----|--------------------------------|--------------------------------|
|  1 |  John |   1 | January, 15 2013 00:00:00+0000 | January, 18 2013 00:00:00+0000 |
|  2 |  John |   2 | January, 19 2013 00:00:00+0000 | January, 21 2013 00:00:00+0000 |
|  3 |  Mary |   1 | January, 17 2013 00:00:00+0000 | January, 18 2013 00:00:00+0000 |
|  4 |  Mary |   2 | January, 20 2013 00:00:00+0000 | January, 22 2013 00:00:00+0000 |
|  5 | Nancy |   1 | January, 17 2013 00:00:00+0000 | January, 20 2013 00:00:00+0000 |
|  6 | Nancy |   2 | January, 25 2013 00:00:00+0000 | January, 30 2013 00:00:00+0000 |

您的姓名是否有多对动作/日期?名称是否唯一?如果没有,结果将不可靠。是的,一个名称将有许多对开始和结束。是的,在结果集中,名称将是唯一的。@MarkBostleman如果名称将有许多对,那么您希望与每对关联的id是什么,带开始的id还是什么?谢谢Dan,我将更新问题,但每个名称不只有一个开始和结束日期。名称开始和结束多次。因此,您是要输出最小开始日期和最大结束日期,还是需要输出每个相邻的开始日期和结束日期对?在后一种情况下,什么是可能重叠的句点?相邻的句点对,而不是重叠的句点对。谢谢Anjali,我会更新这个问题,但每个名字不只有一个开始和结束日期。一个名字开始和结束很多次。