使用SQL Server 2005,我有一个表,其中记录了某些事件,我需要创建一个只返回非常具体结果的查询。下面有一个例子:
Log: Log_ID | FB_ID | Date | Log_Name | Log_Type 7 | 4 | 2007/11/8 | Nina | Critical 6 | 4 | 2007/11/6 | John | Critical 5 | 4 | 2007/11/6 | Mike | Critical 4 | 4 | 2007/11/6 | Mike | Critical 3 | 3 | 2007/11/3 | Ben | Critical 2 | 3 | 2007/11/1 | Ben | Critical
查询应该执行以下操作:每个FB_ID只返回一行,但这必须是第一次更改Log_Name的行,或者如果名称永远不会更改,那么第一个日期行。
在外行人的条款中,我需要这个来浏览数据库以检查案例(FB_ID)的责任移动到另一个人的每个实例,如果它从未有过,那么只需获取原始记录器的名称。
在上面的示例中,我应该获得行(Log_ID)2和6。
这甚至可能吗?现在正在讨论DB是否只是错误的方式。 :)
我想我需要能够以某种方式将第一个产生的Log_Name存储到变量中,然后将其与IF条件等进行比较。我不知道如何用SQL做这样的事情。
编辑:更新了日期。为了澄清这一点,正确的结果将如下所示:
Log_ID | FB_ID | Date | Log_Name | Log_Type 6 | 4 | 2007/11/6 | John | Critical 2 | 3 | 2007/11/1 | Ben | Critical
这不是我之后每个FB_ID的第一个日期,而是Log_Name从原始文件更改的行。
最初FB_ID 4属于Mike,但查询应返回它移动到John的行。但是,它不应该返回进一步移动到Nina的行,因为当John得到它时,第一个责任改变已经发生。
对于具有FB_ID 3的Ben,记录器永远不会更改,因此应该返回Ben的第一行。
答案 0 :(得分:3)
我想有更好,更高效的方式,但这个似乎有用:
SELECT *
FROM log
WHERE log_id IN
( SELECT MIN(log_id)
FROM log
WHERE
( SELECT COUNT(DISTINCT log_name)
FROM log log2
WHERE log2.fb_id = log.fb_id ) = 1
OR log.log_name <> ( SELECT log_name
FROM log log_3
WHERE log_3.log_id =
( SELECT MIN(log_id)
FROM log log4
WHERE log4.fb_id = log.fb_id ) )
GROUP BY fb_id )
答案 1 :(得分:2)
这将有效地使用(fb_id, cdate, id)
上的索引:
SELECT lo4.*
FROM
(
SELECT CASE WHEN ln.log_id IS NULL THEN lo2.log_id ELSE ln.log_id END AS log_id,
ROW_NUMBER() OVER (PARTITION BY lo2.fb_id ORDER BY lo2.cdate) AS rn
FROM (
SELECT
lo.*,
(
SELECT TOP 1 log_id
FROM t_log li
WHERE li.fb_id = lo.fb_id
AND li.cdate >= lo.cdate
AND li.log_id <> lo.log_id
AND li.log_name <> lo.log_name
ORDER BY
cdate, log_id
) AS next_id
FROM t_log lo
) lo2
LEFT OUTER JOIN
t_log ln
ON ln.log_id = lo2.next_id
) lo3, t_log lo4
WHERE lo3.rn = 1
AND lo4.log_id = lo3.log_id
答案 2 :(得分:0)
如果我已正确理解问题,则以下SQL应该可以解决问题:
SELECT Log_ID, FB_ID, min(Date), Log_Name, Log_Type
FROM Log
GROUP BY Date
SQL将为每个FP_ID选择具有最早日期的行。