Как я могу вернуть переменное (n) количество строк с FETCH FIRST (n) ROWS ONLY
в DB2 SQL ..? Это для DB2 / 400 v7r3.
В документации для FETCH
четко указано, что это невозможно, но я не могу представить другого способа сделать это ...
... fetch-row-count не должен содержать скалярную полную выборку, ссылку на столбец, ссылку на таблицу, ссылку на пользовательскую функцию или встроенную скалярную функцию ...
... что я понимаю как значение, которое должно быть константой, такой как "10"
, и не может быть именем переменной или столбца, что, к сожалению, именно то, что я хотел бы сделать.
Это работает:
SELECT PREFILTER.*
FROM PREFILTER
INNER JOIN GT1 ON FILTERED.GTAMT=GT1.LOSTAMT
ORDER BY GTDATE DESC
FETCH FIRST 10 ROWS ONLY
Это не работает:
SELECT PREFILTER.*
FROM PREFILTER
INNER JOIN GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
ORDER BY GTDATE DESC
FETCH FIRST (GT1.LOSTAMT) ROWS ONLY <=== changed here
Получена следующая ошибка:
SQL Error [428H7]: [SQ20467] Expression containing LOSTAMT must calculate a constant value.
Этот запрос предназначен для поиска записей финансовых транзакций, которые осиротели или неправильно введены в большую таблицу с довольно слабой нормализацией и ссылочной целостностью (или их отсутствием).
PREFILTER
- это запрос, который возвращает подмножество основной таблицы, а GT1
- это другой запрос, который вычисляет меньшее и более сложное подмножество этих записей. Затем JOIN
их и возвращаем (n)
строк, как указано в столбце LOSTQTY
, в порядке убывания даты. Поэтому он должен возвращать только (n) самые последние записи.
Обратите внимание, что я признаю, что мое размещение FETCH
является неправильным, и оно (или что бы оно ни превращалось в), вероятно, должно было бы перейти в один из запросов CTE, таких как GT1
.
Кроме того, на этой ранней стадии кажется очевидным, что я получаю некоторые декартовы результаты, но они, вероятно, будут решены, как только проблема FETCH
будет решена.
Для справки, вот полный SQL проекта:
WITH --SET THE INITIAL ACCOUNT & DATE RANGE
PREFILTER AS ( SELECT *
FROM GLTRANT
WHERE GTDATE > 20170000
AND GTACCT=112068
),
--CREATE LIST OF ALL POSITIVE VALUES
POSVALS AS ( SELECT GTAMT AS POSAMT, COUNT(GTAMT) AS POSC
FROM PREFILTER
WHERE GTAMT > 0
GROUP BY GTAMT
),
--CREATE LIST OF ALL NEGATIVE VALUES, WITH SIGN DROPPED
NEGVALS AS ( SELECT ABS(GTAMT) AS NEGAMT, COUNT(GTAMT) AS NEGC
FROM PREFILTER
WHERE GTAMT < 0
GROUP BY ABS(GTAMT)
),
--CALCULATE DISCREPANCIES BETWEEN THE TWO LISTS. SUBTRACT THE TWO AND MULTIPLY THE SIGN BY THE ABSOLUTE VALUE
--OF THE DIFFERENCE. THEN TO RESTORE THE SIGN, MULTIPLY THE AMOUNT BY THE SIGN OF THE DIFFERENCE.
FOJ AS ( SELECT SIGN(COALESCE(POSC,0)-COALESCE(NEGC,0))*COALESCE(POSAMT,NEGAMT) AS LOSTAMT,
ABS (COALESCE(POSC,0)-COALESCE(NEGC,0)) AS LOSTQTY
FROM POSVALS
FULL OUTER JOIN NEGVALS ON POSAMT=NEGAMT
WHERE COALESCE(POSC,0)-COALESCE(NEGC,0) <> 0
),
--GET DISCREPANCIES WITH COUNT >1
GT1 AS ( SELECT *
FROM FOJ
WHERE LOSTQTY>1
)
--SEARCH PREFILTER FOR EACH AMOUNT (LOSTAMT) IN GT1 AND RETURN THE MOST RECENT (LOSTQTY) RECORDS
SELECT PREFILTER.*
FROM PREFILTER
INNER JOIN GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
ORDER BY GTDATE DESC
FETCH FIRST (GT1.LOSTQTY) ROWS ONLY --DOES NOT WORK