【问题标题】:Multi-Column join: Getting additional rows多列连接:​​获取额外的行
【发布时间】:2016-08-15 18:07:53
【问题描述】:

表1:

timezone         some_data       joincol2

America/Denver   22/04/16 7:23   abd
America/Chicago  22/04/16 7:23   abc
America/Adak     22/04/16 7:23   abc
America/Adak     22/04/16 7:23   abe

这是一个数据来自源的事实表。

表2:

timezone         Value_needed      joincol2

America/Chicago    0               NULL
America/Adak      -5               NULL
America/Adak      -4               abc
America/Denver    -2               NULL

这是一个静态表。

期望的结果:在 timezonejoincol2 上加入这些表并从表 2 中获取 value_needed 列,在某种程度上,当 joincol2 匹配时,对应的值将在时区中与 null 相匹配。

我写的查询:

SELECT table1.timezone, 
       table1.joincol2 AS left_joincol2, 
       table2.joincol2 AS right_joincol2, 
       value_needed 
FROM   table1 
       LEFT JOIN table2 
              ON ( table1.joincol2 = table2.joincol2 
                    OR table2.joincol2 IS NULL ) 
                 AND table2.timezone = table1.timezone 

我得到的结果:

timezone        left_joincol2   right_joincol2  value   some_data

America/Denver  abd                             -2      22/04/16 7:23
America/Chicago abc                              0      22/04/16 7:23
America/Adak    abc                             -5      22/04/16 7:23 --Bad Row
America/Adak    abc             abc             -4      22/04/16 7:23
America/Adak    abe                             -5      22/04/16 7:23

我想在上面的结果中删除这个坏行(第 3 行)。我认为我不能应用排名/分区函数来实现这一点,因为会有很多数据,可以允许在表 1 中重复(或者我可以吗?)。

您能帮我找到解决方案吗?我想要的结果(理想情况下应该与 table1 相同的行数):

timezone        left_joincol2   right_joincol2  value   some_data

America/Denver  abd                             -2      22/04/16 7:23
America/Chicago abc                              0      22/04/16 7:23
America/Adak    abc             abc             -4      22/04/16 7:23
America/Adak    abe                             -5      22/04/16 7:23

附:我可以完全控制系统。可以添加主键或您建议的任何内容。 如果我错过了某些信息,请随时询问。

【问题讨论】:

    标签: mysql sql sql-server postgresql join


    【解决方案1】:

    您可以将静态表视为两个表,一个在“joincol2”上连接,另一个在 joincol2 为空。然后将这两个值合并在一起,首先使用所需的值,以便在存在时获胜。比如:

    select t1.*, 
    coalesce(t2.value_needed, t2_default.value_needed) as value_needed
    from table1 t1 
    left join table2 t2 
      on t1.timezone = t2.timezone 
      and t1.joincol2 = t2.joincol2
    left join table2 t2_default 
      on t1.timezone = t2_default.timezone 
      and t2_default.joincol2 is null
    

    【讨论】:

    • 非常感谢,这正是我想要的。听起来更愚蠢,我想从 t2 创建两个表并加入它们。非常感谢伙计。干杯。
    【解决方案2】:

    试试这个查询:

    SELECT timezone, left_joincol2, right_joincol2, value_needed
    FROM (
      SELECT table1.timezone, 
             table1.joincol2 AS left_joincol2, 
             table2.joincol2 AS right_joincol2, 
             value_needed,
             ROW_NUMBER() OVER (PARTITION BY table1.timezone, table1.joincol2
                                ORDER BY CASE 
                                            WHEN table2.joincol2=table1.joincol2 THEN 1 
                                            ELSE 2 
                                         END) AS rn
      FROM table1 
      LEFT JOIN table2 ON table2.timezone = table1.timezone ) AS t
    WHERE t.rn = 1
    

    查询使用ROW_NUMBER 以便在每个table1.timezone, table1.joincol2 分区内选择性地选择正确正确的记录。

    Demo here

    【讨论】:

    • 感谢您的回复。我写了同样的东西,但是如果有多个具有相同 joincol2 的行和多个具有 joincol2 为空的行,这将起作用。另外,我们可以做些什么来提高这个窗口函数的性能?
    • @DeepanshuKalra 你能添加一些示例数据来解释这个案例吗?使用索引是使用窗口函数的方法。
    • -betsos 非常感谢您的帮助。我得到了解决方案。干杯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多