我怎样才能通过"进行分区。在一个基于标准的组内?

时间:2017-01-30 17:26:20

标签: sql database oracle

这似乎是直截了当的,但我无法搞清楚。我有一个表,我在一个组中比较记录(group_id)。我根据与我的研究相关的某些标准给我的记录一个标记。我需要查看大约10个标志。在某些情况下,在组内,只标记了1条记录。在其他情况下,两个记录都被标记。

我现在要做的是根据每个标志指定的日期对group_id进行分区。我有3个时间段我想看看:2016年,2010年 - 2015年,2010年之前,两个记录是相同的。这些反映在我的' file_date'未设置为日期类型数据的字段。相反,他们有一年的abcsum(夏季)和abcwin(冬季)。在某些情况下,此字段为空。

我想做的是创造一个“赢家”的另一面旗帜。分区的基础是哪个日期标准适合。标准的重要性从最近到最近。以下是我希望将进一步解释的一些示例数据:

------------------------------
|group_id  | file_date | flag |
-------------------------------
| a        | abcsum16  | 3    |
| a        | abcwin16  |      |
| b        |  null     |  4   |
| b        | abcsum15  |  4   |
| c        | abcwin16  |  7   |
| c        | abcwin16  |  7   |
| d        | abcsum09  |  3   |
| d        | null      |      |
-------------------------------

输出结果为:

|group_id  | file_date | flag | date_flag |
--------------------------------------------
| a        | abcsum16  | 3    |    1      |
| b        | abcsum15  |  4   |    2      |
| c        | abcwin16  |  7   |    0      |
| c        | abcwin16  |  7   |    0      |
| d        | abcsum09  |  3   |    3      |
-------------------------------------------

1 个答案:

答案 0 :(得分:1)

这是一种方法。但请注意,如果可能的话,在您的过程中尽早使用这些技术会好得多。例如,如果file_date没有以这种方式存储在基表中,而是它是某些处理的结果,那么最好使用基础数据而不是file_date表达式。也许分析函数可以更快地使用,因此您可以减少对数据的传递(当然,假设性能很重要;有时它不是。)

with
     test_data ( group_id, file_date, flag ) as (
       select 'a', 'abcsum16', 3    from dual union all
       select 'a', 'abcwin16', null from dual union all
       select 'b', null      , 4    from dual union all
       select 'b', 'abcsum15', 4    from dual union all
       select 'c', 'abcwin16', 7    from dual union all
       select 'c', 'abcwin16', 7    from dual union all
       select 'd', 'abcsum09', 3    from dual union all
       select 'd', null      , null from dual
     )
-- end of test data (not part of the SQL query); query begins BELOW THIS LINE
select group_id, file_date, flag,
       case when count(*) over (partition by group_id) = 2
                 and
                 count(distinct file_date) over (partition by group_id) = 1 then 0 
            when to_number(substr(file_date, -2)) = 16                      then 1
            when to_number(substr(file_date, -2)) between 10 and 15         then 2
            else                                                                 3 end
                 as date_flag
from   test_data
where file_date is not null and flag is not null
;

GROUP_ID FILE_DATE FLAG  DATE_FLAG
-------- --------- ---- ----------
a        abcsum16     3          1
b        abcsum15     4          2
c        abcwin16     7          0
c        abcwin16     7          0
d        abcsum09     3          3

5 rows selected.