多列连接:​​获取其他行

时间:2016-04-22 08:03:17

标签: mysql sql sql-server postgresql join

表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

这是一张静态表。

DEsired结果:在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

P.S。我对系统有完全的控制权。可以添加主键或您建议的任何内容。 如果我错过了一些信息,请随时询问。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

尝试此查询:

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