sql - 每 2 个月根据不同行的最小(日期)标记列

标签 sql oracle date oracle11g

我有一张这样的表格,其中包含不同投诉的信息

telephone   motive  complaint_id    complaint_date
980761524   motive1 R1234561        23/05/2017
980761524   motive1 R1234562        23/05/2017
980761524   motive1 R1234563        25/08/2017
980761524   motive1 R1234564        26/09/2017
980761524   motive1 R1234565        10/10/2017
980761524   motive1 R1234566        30/12/2017
991761525   motive2 R4454222        24/06/2017
991761525   motive2 R4454223        29/06/2017
991761525   motive2 R4454224        30/10/2017
940789563   motive3 R8993271        24/06/2017
940789563   motive3 R8993272        29/06/2017
940789563   motive3 R8993273        30/10/2017

我需要编写一个查询 (oracle-sql),用 repeat_flag(new column) 标记具有相同电话、相同动机的投诉,其中 min(complaint_date) 为 0,但这个 min (complaint_date) 每 2 个月更改一次。

让我详细解释一下。

假设我正在分析第一组电话/动机是

telephone  motive  complaint_id    complaint_date
980761524   motive1 R1234561        23/05/2017
980761524   motive1 R1234562        23/05/2017
980761524   motive1 R1234563        25/08/2017
980761524   motive1 R1234564        26/09/2017
980761524   motive1 R1234565        10/10/2017
980761524   motive1 R1234566        30/12/2017

这个组的最小(complaint_date)是23/05/2017,这里有两行有相同的日期。因此,为了只留下一个,我转到列 complaint_id 以查看生成的第一个投诉。所有的complaints_id都是R+Number,最小的数字是第一个投诉(R1234561),标记为0。因此,如果下一行的日期是第一个 min(complaint_date) 内的 2 个月,我将其标记为 1。

如果下一个 complaint_date 在两个月内,那么你有一个重复的投诉,你将其标记为 1。在这个例子中,23/05/2017 在其中,所以我将其标记为 1。

如果下一个 complaint_date 不在两个月内,则不是重复,您将其标记为“0”。现在这里的 complaint_date 是 25/08/2017,现在是新的 min(complaint_date)

下一行,这里我得到 26/09/2017,它在 2 个月内 25/08/2017 所以这是一个重复,我将其标记为 1。

下一行,这里我得到 10/10/2017,它在 2 个月内 25/08/2017 所以这是一个重复,我将其标记为 1。

最后,我在这里得到了 30/12/2017,它不在 2 个月内 25/08/2017 所以这不再重复,我将其标记为 .现在是新的 min(complaint_date)

更多行相同。

最终结果应该是这样的

telephone   motive  complaint   complaint_date  2months_repeat_flag
980761524   motive1 R1234561        23/05/2017                   0
980761524   motive1 R1234562        23/05/2017                   1
980761524   motive1 R1234563        25/08/2017                   0
980761524   motive1 R1234563        26/09/2017                   1
980761524   motive1 R1234563        10/10/2017                   1
980761524   motive1 R1234563        30/12/2017                   0

决赛 table 应该是这样的

telephone   motive  complaint   complaint_date  2months_repeat_flag
980761524   motive1 R1234561        23/05/2017                    0
980761524   motive1 R1234562        23/05/2017                    1
980761524   motive1 R1234563        25/08/2017                    0
980761524   motive1 R1234564        26/09/2017                    1
980761524   motive1 R1234565        10/10/2017                    1
980761524   motive1 R1234566        30/12/2017                    0
991761525   motive2 R4454222        24/06/2017                    0
991761525   motive2 R4454223        29/06/2017                    1
991761525   motive2 R4454224        30/10/2017                    0
940789563   motive3 R8993271        24/06/2017                    0
940789563   motive3 R8993272        29/06/2017                    1
940789563   motive3 R8993273        30/10/2017                    0

我的 table 上有大约 2 到 30 起投诉,电话相同,动机相同。

仅使用 SQL 是否可行?欢迎任何存储过程。但我更喜欢仅使用 SQL 来执行此操作,因为我的用户无权创建 sp。

最佳答案

这是一个适用于 Oracle 10 及更高版本的解决方案。它使用 model 子句(match_recognize 子句的远祖)。 match_recognize,在 Oracle 12 及更高版本中可用,可能快几倍,但可能不适用于 OP(问题标记为 oracle11g)。

设置:

alter session set nls_date_format = 'dd/mm/yyyy';

create table test_data ( telephone, motive, complaint_id, complaint_date ) as
    select 980761524, 'motive1', 'R1234561', to_date('23/05/2017') from dual union all
    select 980761524, 'motive1', 'R1234562', to_date('23/05/2017') from dual union all
    select 980761524, 'motive1', 'R1234563', to_date('25/08/2017') from dual union all
    select 980761524, 'motive1', 'R1234564', to_date('26/09/2017') from dual union all
    select 980761524, 'motive1', 'R1234565', to_date('10/10/2017') from dual union all
    select 980761524, 'motive1', 'R1234566', to_date('30/12/2017') from dual union all
    select 991761525, 'motive2', 'R4454222', to_date('24/06/2017') from dual union all
    select 991761525, 'motive2', 'R4454223', to_date('29/06/2017') from dual union all
    select 991761525, 'motive2', 'R4454224', to_date('30/10/2017') from dual union all
    select 940789563, 'motive3', 'R8993271', to_date('24/06/2017') from dual union all
    select 940789563, 'motive3', 'R8993272', to_date('29/06/2017') from dual union all
    select 940789563, 'motive3', 'R8993273', to_date('30/10/2017') from dual
;

commit;

查询:

select telephone, motive, complaint_id, complaint_date, flag
from   test_data
model  
  partition by (telephone, motive)  
  dimension by (row_number() over (partition by telephone, motive 
                                   order by     complaint_date, complaint_id) rn)
  measures (complaint_id, complaint_date, complaint_date s, 0 flag)  
  rules (  
    s[rn>1]    = case when complaint_date[cv(rn)] < add_months(s[cv(rn) - 1], 2)  
                      then s[cv(rn) - 1]  
                      else complaint_date[cv(rn)]  
                 end,
    flag[rn>1] = case when s[cv(rn)] = s[cv(rn) - 1] then 1 else 0 end
  )
order by telephone, motive, rn
;

输出:(通过电话排序,然后根据动机排序——可以根据需要更改)

 TELEPHONE   MOTIVE    COMPLAINT_ID COMPLAINT_DATE FLAG
 ---------   -------   ------------ -------------- ----
 940789563   motive3   R8993271     24/06/2017        0
 940789563   motive3   R8993272     29/06/2017        1
 940789563   motive3   R8993273     30/10/2017        0
 980761524   motive1   R1234561     23/05/2017        0
 980761524   motive1   R1234562     23/05/2017        1
 980761524   motive1   R1234563     25/08/2017        0
 980761524   motive1   R1234564     26/09/2017        1
 980761524   motive1   R1234565     10/10/2017        1
 980761524   motive1   R1234566     30/12/2017        0
 991761525   motive2   R4454222     24/06/2017        0
 991761525   motive2   R4454223     29/06/2017        1
 991761525   motive2   R4454224     30/10/2017        0

关于sql - 每 2 个月根据不同行的最小(日期)标记列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44732389/

相关文章:

sql - 计算sql中多列的平均值/标准差

mysql - 如何在 DBIx::Class 的 SELECT 部分使用子查询?

mysql - MySQL 中的日期时间算法是否需要 INTERVAL?

java - Spring JPA Java [ ORA-01861 文字与格式字符串不匹配 ]

php - 使用 PHP DateInterval 创建重复事件

MySQL - 获取发生事件的月份列表

mysql - 应该以什么顺序(表列或查询)组合索引?

MySQL - 使用 UNION ALL 获取错误的表字段,但结果是正确的

oracle - 将大型 sql 查询作为输入发送到 oracle 中的过程

java - 坚持使用 sql/hql 查询组