如何根据非重复列中的逻辑消除某些列中的重复项

时间:2019-02-13 21:08:08

标签: sql oracle

我正在尝试修改我的这份报告。该报告应该能够识别出一组数据的属性的变化。

例如,某人及其住所续约地址。因此,假设该人从2018年1月1日至2018年3月12日在地址1,然后移至另一个地址2,最初在2018年3月12日至12/31/2021签署了租约,但随后改变了租期至2018年3月12日至2018年10月1日。然后他继续前进,将其租约从10/2/2018延长至12/31/2020。在这种情况下,我不想显示12/31/2021至3/12/2018的初始租赁签署期。当前表存储所有这些记录,我不希望仅显示此特定行,以免最终用户感到困惑。

我的查看方式,如果我能够获得Person,Person_ID,Phone_Number,end_date列中的所有“重复项”,然后对于那些重复的行仅保留最高的start_date,我将可以进行报告正确的方式。但是,我仍然无法在显示所有数据时从这些行中删除min(start_date)。

select 
    subset.person, 
    subset.person_id, 
    subset.phone_number, 
    subset.end_date, 
    count(*)
from subset
group by 
    subset.subset.person, 
    subset.person_id, 
    subset.phone_number, 
    subset.end_date
having count(*)>1
order by person_id;

现在对于这些行,我需要选择max(start_date)并仅将其保留在报告中(我认为我被困在那里)。

因此该表实质上显示了以下内容:

Person  Person ID   Phone Number    Address 1   Zip Code    Start Date  End Date
Jane    1   8792029484  some address-1  12345   3/5/2016    11/9/2018
Jane    1   8792029484  some address-2  34455   11/10/2018  12/31/9999
Jane    1   8792029484  some address-2  34455   11/10/2018  12/7/2018
Jane    1   8792029484  some address-2  34455   12/8/2018   12/31/9999
John    2   9808845768  another address-1   68687   1/1/2013    11/9/2018
John    2   9808845768  another address-2   89384   11/10/2018  12/31/9999
John    2   9808845768  another address-2   89384   11/10/2018  12/7/2018
John    2   9808845768  another address-2   89384   12/8/2018   12/31/9999

对于Jane和John,我不希望显示以下行:

    Jane    1   8792029484  some address-2  34455   11/10/2018  12/31/9999
    John    2   9808845768  another address-2   89384   11/10/2018  12/31/9999

预期结果:

   Person   Person ID   Phone Number    Address 1   Zip Code    Start Date  End Date
   Jane 1   8792029484  some address-1  12345   3/5/2016    11/9/2018
   Jane 1   8792029484  some address-2  34455   11/10/2018  12/7/2018
   Jane 1   8792029484  some address-2  34455   12/8/2018   12/31/9999
   John 2   9808845768  another address-1   68687   1/1/2013    11/9/2018
   John 2   9808845768  another address-2   89384   11/10/2018  12/7/2018
   John 2   9808845768  another address-2   89384   12/8/2018   12/31/9999

2 个答案:

答案 0 :(得分:0)

这是一个查询,可以完成您期望的操作。子查询利用窗口函数ROW_NUMBER()为具有相同PersonID / adress1 / StartDate的记录组中的每个记录分配一个编号。行号按EndDate排序。然后,外部查询仅保留每个组中具有最小EndDate的记录。

SELECT person, personid, phonenumber, address1, zipcode, startdate, enddate
FROM (
    SELECT 
        s.*, 
        ROW_NUMBER() 
            OVER(PARTITION BY personID, address1, startdate ORDER BY enddate) rn
    FROM subset s
) x WHERE rn = 1

demo on DB Fiddle 及其示例数据将返回:

PERSON | PERSONID | PHONENUMBER | ADDRESS1          | ZIPCODE | STARTDATE | ENDDATE  
:----- | -------: | ----------: | :---------------- | ------: | :-------- | :--------
Jane   |        1 |  8792029484 | some-address-1    |   12345 | 05-MAR-16 | 09-NOV-18
Jane   |        1 |  8792029484 | some-address-2    |   34455 | 10-NOV-18 | 07-DEC-18
Jane   |        1 |  8792029484 | some-address-2    |   34455 | 08-DEC-18 | 31-DEC-99
John   |        2 |  9808845768 | another-address-1 |   68687 | 01-JAN-13 | 09-NOV-18
John   |        2 |  9808845768 | another-address-2 |   89384 | 10-NOV-18 | 07-DEC-18
John   |        2 |  9808845768 | another-address-2 |   89384 | 08-DEC-18 | 31-DEC-99

答案 1 :(得分:0)

我猜测您的逻辑是您只希望一行enddate12/31/9999的行,而该行应该来自最近的startdate

如果是这样:

select t.*
from (select t.*,
             row_number() over (partition by person_id, enddate order by startdate desc) as seqnum
      from subset t
     ) t
where enddate <> date '9999-12-31' or seqnum = 1;