SQL Join,选择最早的实例并保留Null

时间:2015-11-19 01:07:49

标签: sql sql-server

我有两个包含以下数据的表:

(File)
    +----+------+...
    | Id | File |
    +----+------+...
    |  1 | Fizz |
    |  2 | Buzz |
    +----+------+...

(Work)    
    +----+------+-----------+-----------+...
    | Id | File |   Step    |   Date    |
    +----+------+-----------+-----------+...
    |  1 | Fizz | Created   | 1/1/2015  |
    |  2 | Fizz | StartWork | 1/2/2015  |
    |  3 | Fizz | WorkDone  | 1/3/2015  |
    |  4 | Buzz | StartWork | 2/16/2015 |
    |  5 | Buzz | WorkDone  | 2/17/2015 |
    |  6 | Buzz | WorkDone  | 2/18/2015 |
    |  7 | Buzz | Closed    | 2/19/2015 |
    +----+------+-----------+-----------+...

我想生成以下结果:

(Query Result)
    +------+-----------+-----------+-----------+-----------+
    | File |  Created  | StartWork | WorkDone  |  Closed   |
    +------+-----------+-----------+-----------+-----------+
    | Fizz | 1/1/2015  | 1/2/2015  | 1/3/2015  | NULL      |
    | Buzz | NULL      | 2/16/2015 | 2/17/2015 | 2/19/2015 |
    +------+-----------+-----------+-----------+-----------+

查询应为任何File返回单行,其中包含Work表中该文件的给定Step的最早实例。例如,'WorkDone'出现在Buzz文件的两个日期,但我希望Joined表只选择2015年2月17日的WorkDone,这是WorkDone发生的最早时间。

此外,对于给定文件不存在的步骤,我想显示NULL。

这是我一直在研究的查询,但我担心我的问题出在了错误的轨道上。我没有捕获NULL条目,我相信我错误地使用了MIN。

SELECT DISTINCT
f.File, 
MIN(workCreated.Date) AS 'Created', 
MIN(workStart.Date) AS 'StartWork', 
MIN(workDone.Date) AS 'WorkDone',
MIN(workClosed.Date) AS 'Closed'
FROM File f
LEFT JOIN Work workCreated ON f.File = workCreated.File
LEFT JOIN Work workStart ON f.File = workStart.File
LEFT JOIN Work workDone ON f.File = workDone.File
LEFT JOIN Work workClosed ON f.File = workClosed.File
WHERE
workCreated.Step = 'Created' AND
workStart.Step = 'StartWork' AND
workDone.Step = 'WorkDone' AND
workClosed.Step = 'Closed'
GROUP BY f.File

2 个答案:

答案 0 :(得分:1)

您必须忽略要加入的ID,而是使用文件和步骤。然后,您可以在最短日期汇总。可以使用案例逻辑,但这会变得有点复杂。严格来说,您不需要使用文件表。

select f.File,
Created=min(c.Date),
StartWork=min(s.Date),
WorkDone=min(d.Date),
Closed=min(l.Date)
from File as f
left join Work as c on f.File=c.File and c.Step='Created'
left join Work as s on f.File=s.File and s.Step='StartWork'
left join Work as d on f.File=d.File and d.Step='WorkDone'
left join Work as l on f.File=l.File and l.Step='Closed'
group by f.File

答案 1 :(得分:0)

一种方法是条件聚合:

select w.file,
       min(case when step = 'Created' then date end) as Created,
       min(case when step = 'StartWork' then date end) as StartWork,
       min(case when step = 'WorkDone' then date end) as WorkDone,
       min(case when step = 'Closed' then date end) as Closed
from Work w
group by w.file;

您的数据结构表明file可能不在Work表中。 id应该是。{1}}。然后你可以加入另一张桌子。