Условно ВЫБЕРИТЕ МАКСИМАЛЬНУЮ дату Oracle SQL - PullRequest
0 голосов
/ 04 июня 2019

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

У меня есть следующие 4 таблицы:

tblPO

| PO Number |    Date    |
|:---------:|:----------:|
| PO2882274 |  6/4/2019  |
| PO1808776 |  6/1/2019  |
| PO1400048 |  5/21/2019 |
| PO6436130 |  4/19/2019 |
| PO4144242 |  2/21/2019 |
| PO7576919 |  1/15/2019 |
| PO1400048 | 12/24/2018 |
| PO6436130 | 11/15/2018 |
| PO6436130 |  1/1/2019  |

tblWO

| WO Number |    Date   |
|:---------:|:---------:|
|  SALE600  | 4/26/2018 |
|  SALE958  | 3/31/2018 |
|  SALE556  |  4/4/2018 |
|  SALE594  |  8/4/2018 |
|  SALE755  | 4/16/2018 |
|  SALE539  | 3/14/2018 |
|  SALE745  | 6/25/2018 |
|  SALE539  |  1/3/2019 |
|  SALE539  |  4/2/2018 |

tblMO

| MO Number |    Date   |
|:---------:|:---------:|
|  MAKE551  | 5/20/2019 |
|  MAKE563  | 1/22/2019 |
|  MAKE504  | 1/27/2019 |
|  MAKE588  | 1/13/2019 |
|  MAKE542  |  1/4/2019 |
|  MAKE614  |  3/8/2019 |
|  MAKE658  | 1/10/2019 |
|  MAKE563  |  1/1/2018 |
|  MAKE551  |  1/1/2019 |

и tblTRX

| Required Date |     Element    | PO Number | WO Number | MO Number | Otherdata |
|:-------------:|:--------------:|:---------:|:---------:|:---------:|:---------:|
|   4/22/2019   | Purchase Order | PO2882274 |           |           |    foo    |
|    1/3/2018   |   Work Order   |           |  SALE600  |           |    foo    |
|   3/22/2019   |   Make Order   |           |           |  MAKE551  |    foo    |
|    5/1/2019   |   Make Order   |           |           |  MAKE563  |    foo    |
|   7/24/2018   |   Make Order   |           |           |  MAKE504  |    foo    |
|   4/28/2018   |   Make Order   |           |           |  MAKE588  |    foo    |
|    7/4/2018   |   Make Order   |           |           |  MAKE542  |    foo    |
|   11/9/2018   |   Make Order   |           |           |  MAKE614  |    foo    |
|   10/2/2018   | Purchase Order | PO7576919 |           |           |    foo    |
|   9/29/2018   |   Work Order   |           |  SALE958  |           |    foo    |
|   6/18/2018   |   Work Order   |           |  SALE556  |           |    foo    |
|   10/9/2018   |   Work Order   |           |  SALE594  |           |    foo    |
|   4/22/2018   |   Work Order   |           |  SALE755  |           |    foo    |
|    4/3/2018   |   Work Order   |           |  SALE539  |           |    foo    |
|   5/11/2018   | Purchase Order | PO6436130 |           |           |    foo    |

Несколько заметок:

  • Первичные ключи в tblPO, tblMO и tblWO могут повторяться , поэтому мне нужно выбрать MAX дату (самую последнюю)
  • Я не могу изменить структуру этих таблиц, и у меня нет прав администратора / доступа к ним

Я пытаюсь написать запрос SQL, который позволил бы мне условно выбрать Date из tblxO в зависимости от того, что это за элемент, а затем присоединиться к его уникальному идентификатору.

Так например ...

| Required Date |     Element    | PO Number | WO Number | MO Number |  TrxDate  | Otherdata |
|:-------------:|:--------------:|:---------:|:---------:|:---------:|:---------:|:---------:|
|   4/22/2019   | Purchase Order | PO2882274 |           |           |  6/4/2019 |    foo    |
|    1/3/2018   |   Work Order   |           |  SALE600  |           | 4/26/2018 |    foo    |
|   3/22/2019   |   Make Order   |           |           |  MAKE551  | 5/20/2019 |    foo    |
|    5/1/2019   |   Make Order   |           |           |  MAKE563  | 1/22/2019 |    foo    |
|   7/24/2018   |   Make Order   |           |           |  MAKE504  | 1/27/2019 |    foo    |
|   4/28/2018   |   Make Order   |           |           |  MAKE588  | 1/13/2019 |    foo    |
|    7/4/2018   |   Make Order   |           |           |  MAKE542  |  1/4/2019 |    foo    |
|   11/9/2018   |   Make Order   |           |           |  MAKE614  |  3/8/2019 |    foo    |
|   10/2/2018   | Purchase Order | PO7576919 |           |           | 1/15/2019 |    foo    |
|   9/29/2018   |   Work Order   |           |  SALE958  |           | 3/31/2018 |    foo    |
|   6/18/2018   |   Work Order   |           |  SALE556  |           |  4/4/2018 |    foo    |
|   10/9/2018   |   Work Order   |           |  SALE594  |           |  8/4/2018 |    foo    |
|   4/22/2018   |   Work Order   |           |  SALE755  |           | 4/16/2018 |    foo    |
|    4/3/2018   |   Work Order   |           |  SALE539  |           |  1/3/2019 |    foo    |
|   5/11/2018   | Purchase Order | PO6436130 |           |           | 4/19/2019 |    foo    |

TrxDate будет следовать такой логике, как:

Если элемент является заказом на поставку, посмотрите в заказе на поставку таблица максимальной даты для номера заказа на поставку данной строки

Я попытался сделать следующее:

CASE
    WHEN TRIM(UPPER(ELEMENT)) = 'PURCHASE ORDER' THEN (SELECT MAX(tblPO.Date) FROM tblPO INNER JOIN tblTRX ON tblTRX.PO_Number = tblPO.PO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'WORK ORDER' THEN (SELECT MAX(tblWO.Date) FROM tblWO INNER JOIN tblTRX ON tblTRX.WO_Number = tblWO.WO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'MAKE ORDER' THEN (SELECT MAX(tblMO.Date) FROM tblMO INNER JOIN tblTRX ON tblTRX.MO_Number = tblPO.MO_Number)
    ELSE NULL
    AS Trx_Date

, который дает данные, однако он выбирает общий максимум для таблицы tblPO (или другой), а не только для конкретной PO_Number для этой строки.

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

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Прежде всего

Первичные ключи в tblPO, tblMO и tblWO могут повторяться

Нет таких вещей, как повторение первичных ключей.Если у вас есть повторяющиеся идентификаторы, то эти идентификаторы не являются первичными ключами.

Теперь, чтобы ответить на ваш вопрос: ваш кейс завершается неудачно, потому что ваши внутренние объединения встраивают в кейс все ссылающиеся на разные экземпляры tblTrx, (у вас может быть 4 отдельных «AS» для именования, по одному для каждого оператора WHEN ив основном из FROM), ничто не ограничивает MAX для вашей текущей транзакции.

Два решения:

1) исправьте ваш случай, заменив объединения словами 'where', чтобы иметь толькоодин экземпляр tblTRX для поиска

CASE
  WHEN TRIM(UPPER(ELEMENT)) = 'PURCHASE ORDER' THEN (SELECT MAX(tblPO.Date) FROM tblPO WHERE tblTRX.PO_Number = tblPO.PO_Number)
  WHEN TRIM(UPPER(ELEMENT)) = 'WORK ORDER' THEN (SELECT MAX(tblWO.Date) FROM tblWO WHERE tblTRX.WO_Number = tblWO.WO_Number)
  WHEN TRIM(UPPER(ELEMENT)) = 'MAKE ORDER' THEN (SELECT MAX(tblMO.Date) FROM tblMO WHERE tblTRX.MO_Number = tblPO.MO_Number)
  ELSE NULL END
 AS Trx_Date

2) Используйте правильные объединения (это будет намного лучше)

SELECT
  [Required Date],
  [Element]
  MAX (
   COALESCE( tblPO.Date , tblWO.Date, tblMO.Date )
  ) AS Trx_Date
FROM tblTRX AS T
  LEFT OUTER JOIN tblPO AS P ON T.PO_Number = P.PO_Number AND TRIM(UPPER(ELEMENT)) = 'PURCHASE ORDER'
  LEFT OUTER JOIN tblWO AS W ON T.WO_Number = W.WO_Number AND TRIM(UPPER(ELEMENT)) = 'WORK ORDER'
  LEFT OUTER JOIN tblMO AS M ON T.MO_Number = M.MO_Number AND TRIM(UPPER(ELEMENT)) = 'MAKE ORDER'
 GROUP BY 
   [Required Date],
   [Element]
1 голос
/ 04 июня 2019

Вы не должны снова ссылаться на вашу базовую таблицу в подзапросах:

SELECT
  CASE
    WHEN TRIM(UPPER(ELEMENT)) = 'PURCHASE ORDER' THEN (SELECT MAX(tblPO.Date) FROM tblPO WHERE tblTRX.PO_Number = tblPO.PO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'WORK ORDER' THEN (SELECT MAX(tblWO.Date) FROM tblWO WHERE tblTRX.WO_Number = tblWO.WO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'MAKE ORDER' THEN (SELECT MAX(tblMO.Date) FROM tblMO WHERE tblTRX.MO_Number = tblPO.MO_Number)
    ELSE NULL END
  AS Trx_Date
FROM tblTRX

должно работать.В противном случае привязка к вашей базовой таблице нарушена.

Причина - другой способ написания вашего запроса следующий:

SELECT
  CASE
    WHEN TRIM(UPPER(ELEMENT)) = 'PURCHASE ORDER' THEN (SELECT MAX(tblPO.Date) FROM tblPO INNER JOIN tblTRX AS T1 ON T1.PO_Number = tblPO.PO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'WORK ORDER' THEN (SELECT MAX(tblWO.Date) FROM tblWO INNER JOIN tblTRX AS T2 ON T2.WO_Number = tblWO.WO_Number)
    WHEN TRIM(UPPER(ELEMENT)) = 'MAKE ORDER' THEN (SELECT MAX(tblMO.Date) FROM tblMO INNER JOIN tblTRX AS T3 ON T3.MO_Number = tblPO.MO_Number)
  ELSE NULL
  AS Trx_Date
FROM tblTRX AS T4

Если вы теперь более внимательно посмотрите на этоВ операторе вы видите, что в подзапросах нет условия, которое уменьшает количество значений в зависимости от внешней таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...