Как я могу сделать SQL-запрос, который обрабатывает отсутствующие записи?

71
4

У меня есть две таблицы, которые содержат возраст и высоту клиентов.

Table: Ages
+-----------+------------+
|customerId | age |
+-----------+------------+
| 1 | 15 |
| 2 | 24 |
| 3 | 21 |
| 4 | 62 |
| 6 | 57 |
| 7 | 32 |
+-----------+------------+

Table: Heights
+-----------+------------+
|customerId | height |
+-----------+------------+
| 1 | 175 |
| 2 | 182 |
| 4 | 180 |
| 5 | 171 |
| 6 | 165 |
| 7 | 182 |
+-----------+------------+

Мне нужно написать запрос SELECT который читает все возрасты и высоты. Так что-то вроде этого...

SELECT Ages.age, Heights.height 
FROM Ages INNER JOIN Heights ON Ages.customerId=Heights.customerId;

Однако (и здесь твист) из-за неаккуратного учета, отсутствуют записи из обеих таблиц. (например, customerId 5 in Ages и customerId 3 в Heights).

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

т.е.

+-----------+------------+------------+
|customerId | age | height |
+-----------+------------+------------+
| 1 | 15 | 175 |
| 2 | 24 | 182 |
| 3 | 21 | 0 |
| 4 | 62 | 180 |
| 5 | 0 | 171 |
| 6 | 57 | 165 |
| 7 | 32 | 182 |
+-----------+------------+------------+

спросил(а) 2014-03-04T18:50:00+04:00 6 лет, 8 месяцев назад
1
Решение
92

Один из способов пойти (они, как всегда, другие)

select customerId, max(age), max(height)
from
(
select customerId, age, 0 as height from Ages
UNION
select customerId, 0 as age, height from heights
) s
group by customerId;

см. SqlFiddle

ответил(а) 2014-03-04T18:56:00+04:00 6 лет, 8 месяцев назад
71

MySql не имеет полного внешнего соединения, но вы можете имитировать один с LEFT JOIN, а затем RIGHT JOIN сочетании с UNION, который объединит + исключить дубликаты:

SELECT Ages.age, COALESCE(Heights.height, 0)
FROM Ages
LEFT OUTER JOIN Heights ON Ages.customerId=Heights.customerId
UNION
SELECT COALESCE(Ages.age, 0), Heights.height
FROM Ages
RIGHT OUTER JOIN Heights ON Ages.customerId=Heights.customerId;

SqlFiddle Here

ответил(а) 2014-03-04T18:54:00+04:00 6 лет, 8 месяцев назад
59

Вам действительно нужно full outer join, но MySQL этого не поддерживает. Вместо этого, получите всех клиентов в подзапросе и используйте left outer join:

select c.customerid, coalesce(a.age, 0) as age, coalesce(h.height, 0) as height
from (select customerid from ages union
select customerid from heights
) c left outer join
ages a
on a.customerid = c.customerid left outer join
heights h
on h.customerid = c.customerid;

ответил(а) 2014-03-04T18:56:00+04:00 6 лет, 8 месяцев назад
42

Использование LEFT JOIN с условием IF является NULL

SELECT Ages.age, IF (Heights.height IS NULL, 0, Heights.height) AS height
FROM Ages
LEFT JOIN Heights ON Ages.customerId=Heights.customerId;

Хорошо, так быстро ответьте... выше только даст вам 0 как высоту. Проблема заключается в том, что возраст возрастает, но для этого лучше получить все идентификаторы клиентов, увеличить возраст и высоту объединения

Лучший ответ - принятый ответ, я оставляю это здесь, потому что я изучил функцию MySQL COALESCE(), XD

ответил(а) 2014-03-04T18:52:00+04:00 6 лет, 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема