ЛЕВОЕ СОЕДИНЕНИЕ — с сохраненной пустой основной записью

#sql #oracle

Вопрос:

У меня есть две связанные таблицы Cars AddItems и соотношение 1 к 0 или много между ними, так что есть автомобили с дополнительными предметами или без них.

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

 CarName | ItemName
======== =========
Car1    |          <- car without additional items
Car2    |          <- car with additional items but this solo record needed as well
Car2    | Item1
Car2    | Item2
Car3    |
Car3    | Item3
 

Если я использую простое ВНЕШНЕЕ СОЕДИНЕНИЕ СЛЕВА, я не смогу получить эту сольную запись автомобиля, когда автомобиль присоединился к дополнительным предметам.

Я мог бы получить что-то вроде:

 SELECT carname,NULL AS itemname FROM cars

UNION

SELECT c.carname,ai.itemname
FROM cars c
LEFT JOIN additems ai ON ai.id_car=c.id
 

Есть ли какой-нибудь более простой/лучший (объединяющий) способ без ОБЪЕДИНЕНИЯ?

Комментарии:

1. Каков ваш конечный результат? Также, пожалуйста, опубликуйте примеры данных из таблицы дополнений?

2. Вы можете заменить на, если вы замените на a . UNION UNION ALL LEFT JOIN JOIN

3. СОЮЗ-это путь сюда. Вам нужна запись из автомобилей (без связи с элементом добавления) И запись для комбинации автомобилей/предметов (внутренняя связь соединения). Единственный способ объединить эти 2-это ОБЪЕДИНЕНИЕ.

Ответ №1:

UNION ALL не выполняет дедупликацию (что необходимо, потому что запрос cars и то и LEFT JOIN другое дают голые автомобили)

UNION это дорого только потому, что удаляет дубликаты, часто вызывая сортировку. В первую очередь дешевле не создавать дубликаты.


    -- all the casrs
SELECT carname,NULL AS itemname
FROM cars

UNION ALL

   -- additional detail records, if any
SELECT c.carname,ai.itemname
FROM cars c
JOIN additems ai ON ai.id_car=c.id
ORDER BY 1,2 NULLS FIRST
        ;
 

Комментарии:

1. Хорошо, я согласен, хотя обе комбинации приведут к одному и тому же набору результатов, комбинация ОБЪЕДИНЕНИЯ ВСЕХ и ОБЪЕДИНЕНИЯ (вместо ОБЪЕДИНЕНИЯ и ОБЪЕДИНЕНИЯ СЛЕВА) является лучшим решением, поскольку идентификатор не включает процесс проверки и удаления повторяющихся записей.

Ответ №2:

Ваша версия в порядке. В качестве альтернативы вы можете использовать БОКОВЫЕ

 SELECT t.*
FROM cars c
CROSS JOIN  LATERAL (
      SELECT c.carname, null FROM DUAL
      UNION ALL
      SELECT c.carname, i.itemname 
      FROM additems i 
      WHERE i.carname = c.carname
    ) t
ORDER BY 1, 2 NULLS FIRST;