SQL-запрос, который запускает новый SQL-запрос для той же строки на основе условия возврата - PullRequest
0 голосов
/ 14 октября 2019

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

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

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

SELECT I.ItemNumber, I.FromLocation, I.ToLocation
FROM ItemLocation AS I
INNER JOIN Delivery AS D
    ON I.ItemNumber = D.ItemNumber
    AND I.FromLocation = D.FromLocation
    AND I.ToLocation = D.ToLocation
WHERE I.Priority IN ('A', 'C')
    AND D.DeliveryStart > 20191001

Проблема с этим запросом состоит в том, что мне нужны только ItemNumbers сприоритет 'C' , если были какие-либо номера элементов с приоритетом 'A'. Теперь я получаю их все независимо. И если 'A' не возвращает какие-либо строки, он должен выполнить тот же запрос, но заменить Приоритет 'A' на 'B', чтобы новое (но все еще ошибочное) предложение WHEREбыть:

WHERE I.Priority IN ('B', 'C')

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

Есть ли способ сделать это в запрос SQL?

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

Попробуйте:

WITH TAB (ItemNumber, Priority) AS 
(
VALUES
  (1, 'A')
, (1, 'C')
, (1, 'D')

, (2, 'B')
, (2, 'C')

, (3, 'A')
, (3, 'B')
, (3, 'C')

, (4, 'C')
)
SELECT ItemNumber, Priority
FROM 
(
SELECT 
  ItemNumber, Priority
, COUNT(CASE Priority WHEN 'A' THEN 1 END) OVER (PARTITION BY ItemNumber) COUNT_A
, COUNT(CASE Priority WHEN 'B' THEN 1 END) OVER (PARTITION BY ItemNumber) COUNT_B
FROM TAB
WHERE Priority IN ('A', 'B', 'C')
)
WHERE 
   Priority = 'A'
OR Priority = 'B' AND COUNT_A = 0
OR Priority = 'C' AND COUNT_A + COUNT_B > 0
;

|ITEMNUMBER |PRIORITY|
|-----------|--------|
|1          |A       |
|1          |C       |
|2          |B       |
|2          |C       |
|3          |A       |
|3          |C       |

Мы используем функцию OLAP COUNT, чтобы получить количество записей с соответствующими Priority в той же группе ItemNumber для каждой записи.
Если этоне ожидаемый результат, затем предоставьте его на данных выше.

0 голосов
/ 14 октября 2019

Рассмотрим LEFT JOIN + UNION подзапросов или CTE для вашей письменной потребности:

Я хочу только номера элементов с приоритетом 'C', если были какие-либо номера элементов с приоритетом 'A'... И если «A» не возвращает никаких строк, он должен выполнить тот же запрос, но заменить приоритет «A» на «B»

WITH A_records AS (
   SELECT I.ItemNumber, I.FromLocation, I.ToLocation
   FROM ItemLocation AS I
   INNER JOIN Delivery AS D
      ON I.ItemNumber = D.ItemNumber
      AND I.FromLocation = D.FromLocation
      AND I.ToLocation = D.ToLocation
   WHERE I.Priority = 'A'
     AND D.DeliveryStart > 20191001
), B_records AS (
   SELECT I.ItemNumber, I.FromLocation, I.ToLocation
   FROM ItemLocation AS I
   INNER JOIN Delivery AS D
      ON I.ItemNumber = D.ItemNumber
      AND I.FromLocation = D.FromLocation
      AND I.ToLocation = D.ToLocation
   WHERE I.Priority = 'B'
     AND D.DeliveryStart > 20191001
), C_records AS (
   SELECT I.ItemNumber, I.FromLocation, I.ToLocation
   FROM ItemLocation AS I
   INNER JOIN Delivery AS D
      ON I.ItemNumber = D.ItemNumber
      AND I.FromLocation = D.FromLocation
      AND I.ToLocation = D.ToLocation
   WHERE I.Priority = 'C'
     AND D.DeliveryStart > 20191001
)

SELECT a.ItemNumber as A_ItemNumber, a.FromLocation As A_FromLocation,
       a.ToLocation As A_ToLocation,
       c.ItemNumber as C_ItemNumber, c.FromLocation As C_FromLocation, 
       c.ToLocation As C_ToLocation
FROM A_records a
LEFT JOIN C_records c
  ON a.ItemNumber = c.ItemNumber

UNION ALL

SELECT B.ItemNumber as B_ItemNumber, B.FromLocation As B_FromLocation,
       B.ToLocation As B_ToLocation,
       c.ItemNumber as C_ItemNumber, c.FromLocation As C_FromLocation, 
       c.ToLocation As C_ToLocation
FROM B_records b
LEFT JOIN C_records c
  ON b.ItemNumber = c.ItemNumber
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...