【问题标题】:Oracle SQL group by column with count but only if the column is null or 0Oracle SQL 按列分组,但仅当该列为空或 0
【发布时间】:2013-01-02 05:46:46
【问题描述】:

简而言之,我试图按列分组,但前提是该列不是 null 或 0,在这种情况下,我仍然想获取这些行,但只是不分组。我有这张桌子some_table:

+--------+----------+---------------------+-------+
| id     | other_id | date_value          | value |
+--------+----------+---------------------+-------+
| 1      | abc      | 2011-04-20 21:03:05 | 104   |
| 2      | abc      | 2011-04-20 21:03:04 | 229   |
| 3      | xyz      | 2011-04-20 21:03:03 | 130   |
| 4      | abc      | 2011-04-20 21:02:09 | 97    |
| 5      | 0        | 2011-04-20 21:02:08 | 65    |
| 6      | xyz      | 2011-04-20 21:02:07 | 101   |
| 7      |          | 2011-04-20 21:02:07 | 200   |
| 8      | 0        | 2011-04-20 21:02:07 | 201   |
| 9      |          | 2011-04-20 21:02:07 | 202   |
+--------+----------+---------------------+-------+

我想选择行并按other_id 分组,还包括分组行的计数。此查询有效:

select id, other_id, date_value, value, cnt from
 (
   SELECT id, other_id, date_value, value, 
   ROW_NUMBER() OVER (partition by other_id order BY Date_Value desc) r,
   count(*) OVER (partition by other_id) cnt
   FROM some_table 
 )
where r = 1

结果是:

+--------+----------+---------------------+-------+-------+
| id     | other_id | date_value          | value | count |
+--------+----------+---------------------+-------+-------+
| 1      | abc      | 2011-04-20 21:03:05 | 104   | 3     |
| 3      | xyz      | 2011-04-20 21:03:03 | 130   | 2     |
| 5      | 0        | 2011-04-20 21:02:08 | 65    | 2     |
| 7      |          | 2011-04-20 21:02:07 | 200   | 2     |
+--------+----------+---------------------+-------+-------+

问题是,我不想将具有other_id 或null 或0 的行分组。所以想要的结果是这样的:

+--------+----------+---------------------+-------+-------+
| id     | other_id | date_value          | value | count |
+--------+----------+---------------------+-------+-------+
| 1      | abc      | 2011-04-20 21:03:05 | 104   | 3     |
| 3      | xyz      | 2011-04-20 21:03:03 | 130   | 2     |
| 5      | 0        | 2011-04-20 21:02:08 | 65    | 1     |
| 7      |          | 2011-04-20 21:02:07 | 200   | 1     |
| 8      | 0        | 2011-04-20 21:02:07 | 201   | 1     |
| 9      |          | 2011-04-20 21:02:07 | 202   | 1     |
+--------+----------+---------------------+-------+-------+

如您所见,除了other_id 为null 或0 时,所有内容都已分组,在这种情况下它们仍处于选中状态,但未分组。我也在尝试通过date_value 订购。

我尝试在OVER 子句中添加WHERE 子句:

OVER (partition by other_id WHERE other_id IS NOT NULL AND other_id IS NOT '0' order BY Date_Value desc)
-- this produces an error: ORA-00907: missing right parenthesis

我曾考虑进行第二个select 查询并尝试将第一个结果堆叠在第二个结果之上,但由于排序原因,我认为这不会奏效。

有没有办法像这样按条件分组?

【问题讨论】:

    标签: sql oracle plsql group-by


    【解决方案1】:

    这样就可以了:

    SQL> select id, other_id, date_value, value, cnt from
      2   (
      3     SELECT id, other_id, date_value, value,
      4     case
      5       when other_id is null or other_id = '0' then 1
      6       else ROW_NUMBER() OVER (partition by other_id order BY Date_Value desc)
      7     end r,
      8     case
      9       when other_id is null or other_id = '0' then 1
     10       else count(*) OVER (partition by other_id)
     11     end cnt
     12     FROM some_table
     13   )
     14  where r = 1
     15  order by id;
    
            ID OTH DATE_VALUE               VALUE        CNT
    ---------- --- ------------------- ---------- ----------
             1 abc 2011-04-20 21:03:05        104          3
             3 xyz 2011-04-20 21:03:03        130          2
             5 0   2011-04-20 21:02:08         65          1
             7     2011-04-20 21:02:07        200          1
             8 0   2011-04-20 21:02:07        201          1
             9     2011-04-20 21:02:07        202          1
    
    6 rows selected.
    
    SQL>
    

    【讨论】:

    • 非常好,确实非常感谢!希望你今天没有在雪地里通勤。
    • Could "case when other_id > 0 then row_numb... else 1 end" 我猜想,但人们总是想知道你是否想过 NULL 问题。
    【解决方案2】:

    试试,

    SELECT id, other_id, date_value, value, cnt 
    FROM
    (
       SELECT id, other_id, date_value, value, 
              ROW_NUMBER() OVER (partition by other_id order BY Date_Value desc) r,
              count(*) OVER (partition by other_id) cnt
       FROM   some_table 
       WHERE  otherID IS NOT NULL OR
              otherID != '0'
    ) AS derivedTable
    WHERE  r = 1
    

    【讨论】:

    • +1 感谢您的建议,但这不包括 null 和 0 行。我仍然想要结果集中的那些,但只是没有分组。
    猜你喜欢
    • 1970-01-01
    • 2017-10-10
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2018-11-17
    • 2019-02-18
    • 1970-01-01
    相关资源
    最近更新 更多