代码之家  ›  专栏  ›  技术社区  ›  QB1979

在两列表中查找对并联接到三列表中

  •  0
  • QB1979  · 技术社区  · 7 年前

    我正试图找出以下问题的解决方案,我需要找到结对员工>管理器并将其打印出来。

    给出的表格为:

    employee            manager
    ----------------------------------
    Bryce Posada        Antony Real  
    Sung Hosey          Aurelio Havlik  
    Joan Strother       Aurelio Havlik  
    Irwin Fulks         Barton Rose  
    Rocco Keplin        Benito Cowboy  
    Efrain Ricketson    Benito Cowboy  
    Patricia Hackenberg Benito Cowboy  
    Paris Sigala        Chuck Lawson  
    Alva Kaul           Ernest Divens  
    Eli Bielecki        Ernest Divens  
    Walton Virden       Ernest Divens  
    Raphael Montesino   Ernest Divens  
    Dewayne Biggs       Lonny Meller  
    Josef Bakken        Marc Margulies  
    Everett Gresham     Marc Margulies  
    Zachariah Yochum    Otto Brannum  
    

    现在,我需要得到如下结果,例如:

    • Anthony Real只管理一个人,因此作为 一对
    • 奥雷里奥·哈夫利克管理着两个人,所以会有一对。
    • Benito Cowboy管理着三个人,所以会有一对一个 记录为空。

    见下文:

    employee_paired1        employee_paired2    manager
    ---------------------------------------------------------
    Bryce Posada            null                Antony Real  
    Sung Hosey              Joan Strother       Aurelio Havlik  
    Irwin Fulks             null                Barton Rose  
    Rocco Keplin            Efrain Ricketson    Benito Cowboy  
    Patricia Hackenberg     null                Benito Cowboy  
    Paris Sigala            null                Chuck Lawson  
    Alva Kaul               Eli Bielecki        Ernest Divens  
    Walton Virden           Raphael Montesino   Ernest Divens  
    Dewayne Biggs           Dewayne Biggs       Lonny Meller  
    Josef Bakken            Everett Gresham     Marc Margulies  
    Zachariah Yochum        Zachariah Yochum    Otto Brannum  
    

    到目前为止,我的代码生成结果,但它们重叠。。。

    编辑:根据我添加的请求 SQL Fiddle

    以及符合本论坛规则的示例代码:

    select * from ( 
    select max(c1.employee) employee1, c2.employee employee2, c1.manager creator from test3 c1
    join test3 c2 on c1.manager = c2.manager
    and c1.employee < c2.employee
    ) a
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   xQbert    7 年前

    Demo on Rextester

    我假设您的样本数据有缺陷: 我不希望看到德瓦因·比格斯(DewayneBiggs)和撒迦利亚·约丘姆(ZachariahYochum)与他们配对。

    employee_paired1        employee_paired2    manager
    ---------------------------------------------------------
    Dewayne Biggs           Dewayne Biggs       Lonny Meller  
    Zachariah Yochum        Zachariah Yochum    Otto Brannum  
    

    我还假设配对的顺序,谁在配对1中,谁不在配对1中并不重要。因此,我使用了简单的按员工列排序的方法,因此姓氏按字母顺序排列的人将始终是单数,而姓氏按字母顺序排列最早的人将始终是pair1中的第一个。

    有点棘手。。。但是使用用户变量(下面的@MGR、@RN)来模拟行数功能,包括数据分区;和功能 mod() 我们可以生成两组数据,一组用于第一列Der\u tab\u col1,另一组用于第二列。我们使用 Mod() 为了将第一列中的数据限制为仅包含奇数行号,我们将其外部连接到第二组数据,这些数据包含每个管理器的偶数行号,并且仅包括那些在管理器上匹配的记录,当行号大于1时,如果存在偶数,则为偶数。这个逻辑在演示中是可见的,因为我为派生表1和派生表2都包含了RN字段。每个派生表(der\u tab\u Col1、der\u tab\u col2)都使用相同的顺序,并针对相同的基本数据集执行,确保我们在每个查询中获得相同的顺序和结果)。

    SELECT Der_tab_Col1.employee as employee_paired1        
         , Der_tab_Col2.employee as employee_paired2    
         , Der_tab_Col1.manager
    FROM (SELECT A.Employee
               , case when @MGR <> A.Manager THEN @RN:=0 end as resetRN
               , @RN:=@RN+1  RN
               , @MGR:=A.Manager as Manager
          FROM SO48874377 A
          CROSS JOIN (Select @RN:=0, @MGR:='') Z
          ORDER BY manager, employee) Der_tab_Col1
    LEFT JOIN (SELECT A.Employee
                    , case when @MGR2 <> A.Manager THEN @RN2:=0 end as resetRN
                    , @RN2:=@RN2+1  RN
                    , @MGR2:=A.Manager as Manager
          FROM SO48874377 A
          CROSS JOIN (Select @RN2:=0, @MGR2:='') Z
          ORDER BY manager, employee) Der_Tab_col2
       on Der_tab_Col1.Manager = Der_tab_Col2.Manager
      and Der_tab_Col1.RN+1 = Der_tab_Col2.RN
    WHERE mod(der_tab_col1.rn,2)=1
    ORDER BY der_tab_col1.manager, Der_tab_Col1.RN;
    

    给我们:

    +----+-------------------+---------------------+----------------+
    |    | employee_paired1  | employee_paired2    |    manager     |
    +----+-------------------+---------------------+----------------+
    |  1 | Bryce Posada      | NULL                | Antony Real    |
    |  2 | Joan Strother     | Sung Hosey          | Aurelio Havlik |
    |  3 | Irwin Fulks       | NULL                | Barton Rose    |
    |  4 | Efrain Ricketson  | Patricia Hackenberg | Benito Cowboy  |
    |  5 | Rocco Keplin      | NULL                | Benito Cowboy  |
    |  6 | Paris Sigala      | NULL                | Chuck Lawson   |
    |  7 | Alva Kaul         | Eli Bielecki        | Ernest Divens  |
    |  8 | Raphael Montesino | Walton Virden       | Ernest Divens  |
    |  9 | Dewayne Biggs     | NULL                | Lonny Meller   |
    | 10 | Everett Gresham   | Josef Bakken        | Marc Margulies |
    | 11 | Zachariah Yochum  | NULL                | Otto Brannum   |
    +----+-------------------+---------------------+----------------+
    

    SQL where子句 mod(der_tab_col1.rn,2) 简单的意思是将RN(行号)除以2,如果有余数,那么它就是奇数,我们需要这些。如果是偶数,那么我们不需要这些,因为偶数行将位于第2列。

    即使使用这种方法进行模拟,也可以看到分析函数的威力。

    注意:如果我们想要3个成对的名称而不是2个,我们可以继续使用左连接和用户变量的概念,并使用mod 3而不是2;所以这里也定义了一种扩展模式。