选择所有行直到给定值的第一次出现

14
针对以下数据:
``` 日期 | 值 | 检查 2009 | 5 | 1 2008 | 5 | 1 2007 | 5 | 1 2006 | 5 | 0 2005 | 5 | 0 2004 | 5 | 1 2003 | 5 | 1 2002 | 5 | 1 ```
我需要选择所有 `check` 列中首次出现 0 的行,从 2009 年开始往回数。
结果为:
``` 日期 | 值 | 检查 2009 | 5 | 1 2008 | 5 | 1 2007 | 5 | 1 ```
我尝试使用 `lag` 函数,但只能检查一个月的时间。
我使用的数据库是 Oracle 10g。
更新:
看起来一切都很顺利,我的测试数据集太小了无法说明性能差异。
3个回答

20
SELECT * FROM mytable where date > (
   SELECT max(date) FROM mytable where check = 0    
) 

4
SELECT  *
FROM    (
        SELECT  m.*,
                MIN(CASE WHEN check = 0 THEN 0 ELSE 1 END) OVER (ORDER BY date DESC)) AS mn
        FROM    mytable
        )
WHERE   mn = 1

甚至更好的是:
SELECT  *
FROM    (
        SELECT  m.*, ROW_NUMBER() OVER (ORDER BY mydate DESC) AS rn
        FROM    mytable m
        ORDER BY
                mydate DESC
        )
WHERE   rownum = DECODE(check, 0, NULL, rn)
ORDER BY
        mydate DESC

后面的查询实际上会在遇到check中第一个零时停止扫描。

只有当内部的ORDER BY被索引满足时,才会“停止扫描”,在这种情况下,您可能会使用第一个版本。否则,Oracle将完全对内部结果集进行排序。 - WW.
当然会。但是这个解决方案只需要一个(date)索引就可以高效地工作,而MAX()解决方案还需要一个(check, date)索引。 - Quassnoi

1
DECLARE @mytable TABLE (date integer, [value] integer, [check] integer)  

INSERT INTO @mytable VALUES (2009, 5, 1)  
INSERT INTO @mytable VALUES (2008, 5, 1)  
INSERT INTO @mytable VALUES (2007, 5, 1)  
INSERT INTO @mytable VALUES (2006, 5, 0)  
INSERT INTO @mytable VALUES (2005, 5, 0)  
INSERT INTO @mytable VALUES (2004, 5, 1)  
INSERT INTO @mytable VALUES (2003, 5, 1)  
INSERT INTO @mytable VALUES (2002, 5, 1)  

SELECT *  
FROM @mytable  
WHERE date > (SELECT MAX(date) FROM @mytable WHERE [Check] = 0)

不确定在Oracle中是否可以使用“DECLARE @mytable TABLE” :) - Quassnoi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接