Oracle - 在DENSE_RANK中处理NULLS

时间:2015-10-28 21:27:34

标签: sql oracle

我有这个表结构

+----------------+----------------+
|      DATE      |      VALUE     |
|----------------|----------------|
|  2015-01-01    |       5        |
|  2015-01-02    |       4        |
|  2015-01-03    |      NULL      |
|  2015-02-10    |       2        |
|  2015-02-25    |       1        |
+----------------+----------------+

我试图在每个月内获得最新的非null 值。在这种情况下,就是这样:

+----------------+----------------+
|      MONTH     |      VALUE     |
|----------------|----------------|
|     2015-01    |       4        |
|     2015-02    |       1        |
+----------------+----------------+

我已经尝试过DENSE_RANK但是我很难处理空值。

使用:

package so_q33378870;

public class main {

    private static final String[] tests = {
        //Single - Balanced.
        "()",
        //Single - Unbalanced by missing end.
        "(_",
        //Multiple - Balanced.
        "()[]{}<>",
        //Multiple - Unbalanced by missing beginning.
        "()[]_}<>",
        //Nested - Balanced.
        "([{<>}])",
        //Nested - Unbalanced by missing end.
        "([{<>}_)",
        //Endurance test - Balanced.
        "the_beginning (abcd) divider (a[bc]d) divider (a[b{c}d]e) divider (a[b{c<d>e}f]g) the_end"
    };

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        BalanceChecker checker = new BalanceChecker();
        for (String s : tests) {
            System.out.println("\"" + s + "\" is " + ((checker.isBalanced(s)) ? "BALANCED!" : "UNBALANCED!"));
        }
    }
}

我正在

+----------------+----------------+
|      MONTH     |      VALUE     |
|----------------|----------------|
|     2015-01    |      NULL      |
|     2015-02    |       1        |
+----------------+----------------+

显然我做错了什么。 你能帮我搞清楚吗?

提前致谢。

编辑:很遗憾,添加条件

"WHERE value IS NOT NULL"
无法应用于我的情况。

4 个答案:

答案 0 :(得分:0)

此解决方案消除了空值,并使用row_number获取每个月的最新日期和相应值。

select myr, value
from (
SELECT date, value,TO_CHAR(date,'YYYY-MM') myr,
row_number() over(partition by TO_CHAR(date,'YYYY-MM') order by date desc) rn 
FROM mytable
where value is not null) t
where rn = 1

答案 1 :(得分:0)

不幸的是,据我所知,MAX() KEEP没有IGNORE NULLS条款。但LAST_VALUE确实如此。那么,这个怎么样:

SELECT mth,
       MAX (last_val)
FROM   (SELECT TO_CHAR (d, 'YYYY-MM') mth,
               d,
               n,
               LAST_VALUE (
                 n IGNORE NULLS)
               OVER (PARTITION BY TO_CHAR (d, 'YYYY-MM')
                     ORDER BY d ASC
                     ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
                 last_val
        FROM   matt_test)
GROUP BY mth

答案 2 :(得分:0)

我对SELECT ... FROM (SELECT ... FROM ...)这样的建设有个人厌恶,所以这是我的建议:

SELECT DISTINCT 
TRUNC(THE_DATE, 'MM') AS MONTH,
FIRST_VALUE(THE_VALUE IGNORE NULLS) OVER (PARTITION BY TRUNC(THE_DATE, 'MM') ORDER BY THE_VALUE) AS VALUE
FROM MY_TABLE;

答案 3 :(得分:0)

由于分组依据和许多其他原因,我无法使用LAST_VALUE。 所以这对我有用,示例行:

SELECT
  MAX(the_value) KEEP (dense_rank LAST ORDER BY (CASE WHEN the_value IS NOT NULL THEN 1 END) NULLS FIRST, the_date) the_value
FROM ...

或类似的话:

SELECT
  MAX(the_value) KEEP (dense_rank FIRST ORDER BY (CASE WHEN the_value IS NOT NULL THEN 1 END) NULLS LAST, the_date DESC) the_value
FROM ...