Postgres: полное объединение на двух полях (проблема с пропуском данных)

У меня есть два подзапроса, которые создают эти таблицы:

 date      | name | data x
-----------+------+-------
2013-07-01 | a    |   2
2013-07-01 | c    |   3
2013-07-01 | d    |   1

 date      | name | data y
-----------+------+-------
2013-07-01 | a    |   13
2013-07-01 | b    |   16
2013-07-01 | d    |   20

Я хочу сделать полное объединение, используя дату и имя в качестве критерия соединения. (Дата не ограничена 2013-07-01, поэтому в действительности поле даты и поле имени образуют уникальное поле псевдоидентификатора.)

В идеале результат должен выглядеть примерно так:

 date      | name | data x | data y
-----------+------+--------+-------
2013-07-01 | a    |   2    |  13
2013-07-01 | b    |        |  16
2013-07-01 | c    |   3    |    
2013-07-01 | d    |   1    |  20

(Лучше всего, если я могу поставить нули для нуля, но об этом можно будет поговорить позже.)

Я использовал запрос, похожий на этот:

select 
table1.date, table1.name, table1.dataX, table2.dataY
from table1
full join table2 on table1.date=table2.date and table1.name=table2.name

Postgres вводит только те поля, которые существуют в обеих таблицах (в этом примере только строки с именами a и c), что на самом деле лишает смысла полное соединение.

Я пробовал другой способ устранения неполадок, единственный, который работал до сих пор:

select 
table1.date, table2.date, table1.name, table2.name, table1.dataX, table2.dataY
from table1
full join table2 on table1.date=table2.date and table1.name=table2.name

возвращает:

 date      |date        | name | name | data x | data y
-----------+------------+------+------+--------+-------
2013-07-01 | 2013-07-01 |  a   |   a  |   2    |  13
           | 2013-07-01 |      |   b  |        |  16
2013-07-01 |            |  c   |      |   3    |    
2013-07-01 | 2013-07-01 |  d   |   d  |   1    |  20

Есть обходные пути, чтобы сделать это, когда я использую данные, но на самом деле это не идеально. Есть ли способ заставить запрос вернуть желаемый результат?

Потерять немного волос здесь. Огромное спасибо!

1 ответ

Решение

Не используйте WHERE оговорка, но JOIN состояние. USING Статья пригодится:

SELECT the_date, name, t1.data_x, t2.data_y
FROM   tbl1 t1
FULL   JOIN tbl2 t2 USING (the_date, name);

Чтобы доказать свою точку зрения, это может быть сделано без USING:

SELECT COALESCE(t1.the_date, t2.the_date) AS the_date
      ,COALESCE(t1.name, t2.name) AS name
      ,t1.data_x, t2.data_y
FROM   tbl1 t1
FULL   JOIN tbl2 t2 ON t1.the_date = t2.the_date
                   AND t1.name = t2.name

Может быть полезно для связанных запросов. Первый из них более элегантный, немного быстрее, а также стандартный SQL.

-> SQLfiddle (демонстрирует оба)

Другие вопросы по тегам