【问题标题】:Multi-Row function to filter out Duplicates过滤掉重复项的多行函数
【发布时间】:2018-09-29 01:36:07
【问题描述】:

我在使用 SQL 方面相对较新,所以我希望您能帮助我处理一个案例。

我有下表(只是一个示例):

| id | FName_LVL1  | LName_LVL1 | FName_LVL2 | LName_LVL2  |
|----|-------------|------------|------------|-------------|
| 1  | John        | Kennedy    | Marc       | Guy         |
| 2  | John        | Kennedy    | Olivier    | Oslo        |
| 3  | Mike        | Lanes      | Patrick    | James       |

我想隔离 FName_LVL1 和 LName_LVL1 中的重复项

所以表格看起来像这样:

| id | FName_LVL1  | LName_LVL1 | FName_LVL2 | LName_LVL2  |
|----|-------------|------------|------------|-------------|
| 1  | John        | Kennedy    | Marc       | Guy         |
| 2  | John        | Kennedy    | Olivier    | Oslo        |

我的想法是创建一个标志列,条件是列 FName_LVL1 和 LName_LVL1 的上方或下方的 IF 行相同,然后输入“1”,否则输入“0”

有一个如下所示的列:

| id | FName_LVL1  | LName_LVL1 | FName_LVL2 | LName_LVL2  | Flag
|----|-------------|------------|------------|-------------|
| 1  | John        | Kennedy    | Marc       | Guy         | 1
| 2  | John        | Kennedy    | Olivier    | Oslo        | 1
| 3  | Mike        | Lanes      | Patrick    | James       | 0

有了这样的表格后,我可以过滤并获得想要的结果。

这是我在 Alteryx 中习惯的一种工作方式,但我不确定这是否可以使用 SQL 语句,或者即使这是解决这种情况的最佳方式

【问题讨论】:

    标签: sql oracle filter flags multirow


    【解决方案1】:

    no_of_records 是一列,它告诉您该组合在表中出现的次数。 IE。在您的示例表中它将是 2

    select table1.*
    from table as table1
    inner join
    (
      Select FName_LVL1, LName_LVL1, count(*) as no_of_records
      from Table
      group by FName_LVL1, LName_LVL1
    ) table2
      on table1.FName_LVL1 = table2.FName_LVL1
         and table1.LName_LVL1 = table2.LName_LVL1
         and no_of_records>1
    

    【讨论】:

      【解决方案2】:

      您可以将count()window 函数一起使用。

      SQL Fiddle

      查询 1

      SELECT t.*
          ,CASE 
              WHEN COUNT(*) OVER (
                      PARTITION BY fname_lvl1
                      ,lname_lvl1
                      ) > 1
                  THEN 1
              ELSE 0
              END AS Flag
      FROM t
      

      Results

      | ID | FNAME_LVL1 | LNAME_LVL1 | FNAME_LVL2 | LNAME_LVL2 | FLAG |
      |----|------------|------------|------------|------------|------|
      |  1 |       John |    Kennedy |       Marc |        Guy |    1 |
      |  2 |       John |    Kennedy |    Olivier |       Oslo |    1 |
      |  3 |       Mike |      Lanes |    Patrick |      James |    0 |
      

      【讨论】:

      • 这将与 count 一起使用,但与部门一起使用。您没有涉及任何分析功能。
      • @Soldie :请检查答案,如果有帮助,请告诉我。另外,请阅读:stackoverflow.com/help/someone-answers
      【解决方案3】:

      您可以使用“半连接”子查询来获得这样的结果:

      SELECT * FROM Table1 t1
      WHERE EXISTS (
        SELECT 'Anything' FROM Table1 t2
        WHERE t1.FName_LVL1 = t2.FName_LVL1
          AND t1.LName_LVL1 = t2.LName_LVL1
          AND t1.id <> t2.id
      )
      

      演示:http://sqlfiddle.com/#!4/f9c44/3

      | ID | FNAME_LVL1 | LNAME_LVL1 | FNAME_LVL2 | LNAME_LVL2 |
      |----|------------|------------|------------|------------|
      |  2 |       John |    Kennedy |    Olivier |       Oslo |
      |  1 |       John |    Kennedy |       Marc |        Guy |
      

      【讨论】:

        【解决方案4】:

        您可能更喜欢使用LAGLEAD 分析函数以及NVL2 的贡献:

        select n.*,
               nvl2(lag(FName_LVL1||' '||LName_LVL1,1,null) over 
               (partition by FName_LVL1||' '||LName_LVL1 order by FName_LVL1, LName_LVL1),1,0)+
               nvl2(lead(FName_LVL1||' '||LName_LVL1,1,null) over 
               (partition by FName_LVL1||' '||LName_LVL1 order by FName_LVL1, LName_LVL1),1,0) flag
          from names n;
        
        ID FNAME_LVL1   LNAME_LVL1  FNAME_LVL2  LNAME_LVL2  FLAG
        --  ----------  ----------  ----------  ----------  -----
        1    John        Kennedy      Marc        Guy         1
        2    John        Kennedy      Olivier     Oslo        1
        3    Mike        Lanes        Patrick     James       0
        

        SQL Fiddle Demo

        【讨论】:

          【解决方案5】:

          最有效的方法是使用 partition by 子句只进行一次表扫描。 我已将输出保存在Livesql

          drop table t1 purge;
                create table t1 ( c1 varchar2(20), c2 varchar2(20), c3 varchar2(20), c4 varchar2(20));
                insert into t1 values ('John','Kennedy','Marc','Guy');
                insert into t1 values ('John','Kennedy','Olivier','Oslo');
                insert into t1 values ('not','john','vijay','balebail');
                commit;
                select t1.*, count(c1||c2) over (partition by c1,c2 order by c1,c2  ) flag from t1;
                select t1.*, decode (count(c1||c2) over (partition by c1,c2 order by c1,c2  ),1,0,1) flag from t1;
          

          C1 C2 C3 C4 标志 约翰肯尼迪马克盖伊 2 约翰肯尼迪奥利维尔奥斯陆 2 不是约翰·维杰·巴勒拜尔 1 下载 CSV 选择了 3 行。 声明 7 select t1.*, decode (count(c1||c2) over (partition by c1,c2 order by c1,c2 ),1,0,1) flag from t1

          C1 C2 C3 C4 标志 约翰肯尼迪马克盖伊 1 约翰肯尼迪奥利维尔奥斯陆 1 不是约翰·维杰·巴勒拜尔 0

          【讨论】:

            【解决方案6】:

            谢谢大家!看来这个案子确实有很多解决方案!

            我会继续深入研究,看看我最喜欢哪个,但多亏了你,它让我对 SQL 逻辑有了一个很好的了解

            抱歉,我的回复延迟了,我出差了

            【讨论】:

              猜你喜欢
              • 2018-11-01
              • 1970-01-01
              • 2013-01-10
              • 1970-01-01
              • 2020-03-29
              • 1970-01-01
              • 1970-01-01
              • 2019-10-16
              相关资源
              最近更新 更多