Выбор Oracle SQL с условием a, если условие b не существует

Я застрял с существующими и не существующими ключевыми словами.

У меня есть таблица (таблица Oracle Portal), которая в сумме имеет следующую структуру:

ID    LANGUAGE    CAPTION
1     NL          DUTCH CAPTION
1     F           FRENCH CAPTION
2     NL          DUTCH CAPTION
3     F           FRENCH CAPTION

Мне нужен выбор, который всегда выбирает две строки для каждого идентификатора, даже если строка F или строка NL не существует. Затем следует выбрать строку с несуществующим языком на языке столбца, но с заголовком существующей строки (с языком F).

Итак, результат запроса должен быть:

ID    LANGUAGE    CAPTION
1     NL          DUTCH CAPTION
1     F           FRENCH CAPTION
2     NL          DUTCH CAPTION
2     F           DUTCH CAPTION
3     F           FRENCH CAPTION
3     NL          FRENCH CAPTION

Это возможно?

Очень любопытно, и уже большое большое спасибо!!

PS: у меня есть что-то подобное, но это совершенно не то, что я хочу.

SELECT id, language, display_name
FROM portal.wwsbr_all_folders p 
WHERE caid = 55 
AND DISPLAY_IN_PARENT_FOLDER = 1 
AND ((upper(language) = 'NL' AND not exists (SELECT * FROM portal.wwsbr_all_folders p2 WHERE p.id = p2.id and language IN ('F')))
      OR
      (upper(language) = 'F' AND not exists (SELECT * FROM portal.wwsbr_all_folders p2 WHERE p.id = p2.id and language IN ('NL')))
    )
AND parent_id = 4030963 
ORDER BY sub_folder_sequence

РЕДАКТИРОВАТЬ: теперь я получаю правильные результаты со следующим запросом

(SELECT id, CASE language WHEN 'nl' THEN 'f' ELSE 'f' END lang, display_name
FROM portal.wwsbr_all_folders p 
WHERE caid = 55 
AND DISPLAY_IN_PARENT_FOLDER = 1 
AND ((language = 'f' and exists(SELECT * FROM portal.wwsbr_all_folders p2 WHERE p2.id = p.id AND language = 'f')) 
    OR (language = 'nl' and not exists(SELECT * FROM portal.wwsbr_all_folders p2 WHERE p2.id = p.id AND language = 'f')))
AND parent_id = 4656102)
UNION ALL
(
SELECT id, CASE language WHEN 'f' THEN 'nl' ELSE 'nl' END lang, display_name
FROM portal.wwsbr_all_folders p 
WHERE caid = 55 
AND DISPLAY_IN_PARENT_FOLDER = 1 
AND ((language = 'nl' and exists(SELECT * FROM portal.wwsbr_all_folders p2 WHERE p2.id = p.id AND language = 'nl')) 
    OR (language = 'f' and not exists(SELECT * FROM portal.wwsbr_all_folders p2 WHERE p2.id = p.id AND language = 'nl')))
AND parent_id = 4656102)

person Verthosa    schedule 15.10.2013    source источник


Ответы (2)


У вас всего два языка? Если это так, вы можете попробовать следующее решение:

WITH
  my_data AS
    (           SELECT 1 AS id, 'NL' AS language, 'DUTCH CAPTION' AS caption FROM dual
      UNION ALL SELECT 1 AS id, 'F' AS language, 'FRENCH CAPTION' AS caption FROM dual
      UNION ALL SELECT 2 AS id, 'NL' AS language, 'DUTCH CAPTION' AS caption FROM dual
      UNION ALL SELECT 3 AS id, 'F' AS language, 'FRENCH CAPTION' AS caption FROM dual)
SELECT
      id, language, caption
  FROM my_data md
UNION ALL
SELECT
      id, DECODE(language, 'NL', 'F', 'NL'), caption
  FROM my_data md
WHERE NOT EXISTS (SELECT 1
                    FROM my_data
                  WHERE id = md.id
                    AND language != md.language)
ORDER BY id, language;
person Przemyslaw Kruglej    schedule 15.10.2013
comment
Спасибо за ваш ответ, я только что нашел другое решение, которое также возвращает правильные результаты. Я не знаю, какой из них лучше (оптимизатор и загрузчик)... см. мое редактирование в «вопросе» - person Verthosa; 15.10.2013
comment
@Vertosa Я думаю, что мое решение быстрее, у вас больше подзапросов. - person Przemyslaw Kruglej; 15.10.2013

что-то вроде следующего.

если у вас есть дополнительная таблица с идентификаторами, вы можете использовать ее вместо id_list и опустить часть WITH.

WITH id_list AS 
( SELECT DISTINCT id FROM portal_table)
SELECT *
FROM 
(
    -- FRENCH
    SELECT 
      i.id  as id
    , 'F'   as language 
    , NVL(f.CAPTION, NL.CAPTION) AS CAPTION
    FROM 
        id_list  i 
      LEFT OUTER JOIN portal_table f   ON (f.id = i.id  AND f.language = 'F') 
      LEFT OUTER JOIN portal_table nl  ON (nl.id = i.id AND nl.language = 'NL') 
  UNION
      -- DUTCH 
    SELECT 
      i.id  as id
    , 'NL'  as language 
    , NVL(NL.CAPTION, F.CAPTION) AS CAPTION
    FROM 
        id_list  i 
      LEFT OUTER JOIN portal_table f   ON (f.id = i.id  AND f.language = 'F') 
      LEFT OUTER JOIN portal_table nl  ON (nl.id = i.id AND nl.language = 'NL') 
)
order by id
;
person schurik    schedule 15.10.2013
comment
Вы проверили это? Во-первых, в нем есть синтаксические ошибки (вы пропустили ключевые слова JOIN), а во-вторых, он не возвращает правильный набор результатов — некоторые записи имеют NULL в столбце CAPTION, а все остальные записи имеют FRENCH CAPTION. - person Przemyslaw Kruglej; 15.10.2013