У меня есть следующая схема базы данных Sybase (сводится к таблицам вопросов):
___________ ___________ ________
| MyEvent | | EventKind | | Record |
|———————————| |———————————| |————————|
| ID | -->| ID | -->| ID |
| Date | | | Label | | | No |
| Amount | | |___________| | | Date |
| kind_ID |-FK-^ | |________|
| record_ID |--------FK--------------^
|___________|
Меня попросили запросить определенный период для Record
s, имеющих MyEvent
s с указаннымLabel
s (E2
, I5
) и суммируйте Amount
s других MyEvent
s, помеченных K0
, K1
или K2
, если они есть, в противном случае этот столбец таблицы результатовдолжен показать 0
. Таблица результатов должна выглядеть следующим образом:
Наиболее важные и сложные требования:
- выбранные записи, которые содержат хотя бы одно событие, помеченное как E2 или I5, могут содержатьоба
- суммируют суммы событий, помеченных
K0
, K1
и K2
, если они есть в записи, в противном случае возвращают 0
_______________________________________________________________________________
| Record.No | Record.Date | MyEvent.Date | MyEvent.Date | SUM of MyEvent.Amount |
| | | E2 | I5 | K0, K1 and K2 |
———————————————————————————————————————————————————————————————————————————————
| 12345 | 2019-10-01 | NULL | 2019-10-10 | 52,20 |
| 23456 | 2018-02-15 | 2018-02-30 | 2018-05-10 | 34,80 |
| 34567 | 2017-06-26 | NULL | 2017-07-04 | 0 |
| 45678 | 2015-03-17 | 2017-07-04 | NULL | 129,10 |
———————————————————————————————————————————————————————————————————————————————
В настоящее время я не могучтобы получить какой-либо результат, хотя я уверен, что есть тонны Record
с одним из MyEvent
s E2
и I5
(или обоими), а также многие из них с пометкой MyEvent
sK0
, K1
или K2
.
Мой текущий подход заключается в следующем, который использует CASE WHEN ... THEN ... ELSE ... END
, но в настоящее время приходится повторно использовать подзапросы (в любом случае, уродливо, но, очевидно, неправильно):
SELECT DISTINCT
r.No AS "Record.No",
----------------------------------------------------------------
r.Date AS "Record.Date",
----------------------------------------------------------------
CASE
WHEN NOT EXISTS (
SELECT FIRST
MyEvent.Date
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label = 'E2'
) THEN NULL
ELSE (
SELECT FIRST
MyEvent.Date
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label = 'E2'
) END AS "MyEvent.Date E2",
----------------------------------------------------------------
CASE
WHEN NOT EXISTS (
SELECT FIRST
MyEvent.Date
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label = 'I5'
) THEN NULL
ELSE (
SELECT FIRST
MyEvent.Date
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label = 'I5'
) END AS "MyEvent.Date I5",
----------------------------------------------------------------
CASE
WHEN (
SELECT
SUM(MyEvent.Amount)
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label IN ('K0', 'K1', 'K2')
) IS NULL THEN 0
ELSE (
SELECT
SUM(MyEvent.Amount)
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
EventKind.Label IN ('K0', 'K1', 'K2')
) END AS "Sum of MyEvent.Amount K0, K1 and K2"
----------------------------------------------------------------
FROM
Record r
INNER JOIN MyEvent e ON e.record_ID = r.ID
INNER JOIN EventKind k ON k.ID = e.kind_ID
WHERE
a.clientNo IN (515, 520, 521, 522, 535, 632, 832, 853, 889, 890, 892, 893, 894, 895, 934)
AND
a.Date BETWEEN '2008-01-01' AND '2018-12-31'
AND
EXISTS (
SELECT FIRST
MyEvent.Date
FROM
MyEvent
INNER JOIN EventKind ON EventKind.ID = MyEvent.kind_ID
WHERE
MyEvent.record_ID = r.ID
AND
(
EventKind.Label = 'I5'
OR
EventKind.Label = 'E2'
)
)
ORDER BY
r.No ASC
При использовании этого запроса первое, что я получаю, это предупреждение, которое уже является подсказкой, указывающей на что-то не так с запросом :
Второе, что я получаю, это, к сожалению, 0 rows returned
, который определеннона самом деле это не желаемый вывод ;-)
Ожидаемый вывод - 58200 строк с правильными датами и суммами событий.
РЕДАКТИРОВАТЬ
После исправления нескольких ошибок в запросе я теперь получаю правильное количество результатов, и все случайные выборки, которые я проверил, верны, , но предупреждение о недетерминированности результата все равно показывает .
Как мне от этого избавиться? Это заставляет меня чувствовать себя плохо, потому что это подразумевает, возможно, разные результаты для разных занятий, не так ли? До сих пор я выполнял его 5 раз, и результаты были равны…
Если у кого-нибудь есть предложения по сокращению кода SQL, я бы с удовольствием их прочитал.