Вот как это работает в настоящее время: первый запрос выбора возвращает список параметров.
SELECT character_id, foe_id, location_id, date_time, damage, points
FROM events
ORDER BY date_time DESC
LIMIT 100
Теперь следующее повторяется 100 раз для завершения данных, например, возвращается первый:
character_id = 12695
, location_id = 818
, foe_id = 33997
, date_time = '2024-05-02 23:00:00'
Следующий запрос основан на этих результатах:
SELECT *, A1+B1-C1-D1-E1-F1+G1+H1 AS A2
FROM
(SELECT *
FROM
(SELECT id_, cnt_7, date_diff_7 , NTH_VALUE (A0,1) OVER() AS A1, NTH_VALUE (A0,2) OVER() AS B1, NTH_VALUE (B0,1) OVER() AS C1, NTH_VALUE (B0,2) OVER() AS D1
FROM
(SELECT damage AS A0, points AS B0, RootQuery_7.id as id_, count(*) over() as cnt_7, max(date_diff) over() as date_diff_7
FROM
(SELECT *, extract(day from date_time - lag(date_time) over (ORDER BY date_time)) as date_diff
FROM events
WHERE character_id = 12695
AND status = 1
AND location_id = 818
AND date_time < '2024-05-02 23:00:00'
ORDER BY date_time DESC
LIMIT 10 OFFSET 0) AS RootQuery_7)
AS BaseQuery7 LIMIT 1) wnd_1
JOIN (SELECT id_, cnt_8, date_diff_8 , NTH_VALUE (D0,2) OVER() AS H1, NTH_VALUE (C0,1) OVER() AS E1, NTH_VALUE (C0,2) OVER() AS F1, NTH_VALUE (D0,1) OVER() AS G1 FROM
(SELECT damage AS C0, points AS D0, RootQuery_8.id as id_, count(*) over() as cnt_8, max(date_diff) over() as date_diff_8 FROM
(SELECT *, extract(day from date_time - lag(date_time) over (ORDER BY date_time)) as date_diff FROM events WHERE foe_id = 33997 AND status = 1 AND location_id = 818 AND date_time < '2024-05-02 23:00:00' ORDER BY date_time DESC LIMIT 15 OFFSET 0)
AS RootQuery_8)
AS BaseQuery8 LIMIT 1) wnd_2
ON wnd_1.id_ <> 0 WHERE cnt_7 >= 10 AND date_diff_7 <= 150 AND cnt_8 >= 10 AND date_diff_8 <= 150) AS layer_1
Это работает, но слишком неэффективно и медленно, не обращайте внимания на правдоподобие полученных данных, поскольку это пример.
Я пытаюсь получить этот список результатов из одного запроса следующим образом:
(SELECT character_id, foe_id, location_id, date_time, damage, points FROM events ORDER BY date_time DESC LIMIT 100) ref_
JOIN
SELECT *, A1+B1-C1-D1-E1-F1+G1+H1 AS A2 FROM
(SELECT * FROM
(SELECT id_, cnt_7, date_diff_7 , NTH_VALUE (A0,1) OVER() AS A1, NTH_VALUE (A0,2) OVER() AS B1, NTH_VALUE (B0,1) OVER() AS C1, NTH_VALUE (B0,2) OVER() AS D1 FROM
(SELECT damage AS A0, points AS B0, RootQuery_7.id as id_, count(*) over() as cnt_7, max(date_diff) over() as date_diff_7 FROM
(SELECT *, extract(day from date_time - lag(date_time) over (ORDER BY date_time)) as date_diff FROM events WHERE character_id = ref_.character_id AND status = 1 AND location_id = ref_.location_id AND date_time < location_id = ref_.date_time ORDER BY date_time DESC LIMIT 10 OFFSET 0)te_time
AS RootQuery_7)
AS BaseQuery7 LIMIT 1) wnd_1
JOIN (SELECT id_, cnt_8, date_diff_8 , NTH_VALUE (D0,2) OVER() AS H1, NTH_VALUE (C0,1) OVER() AS E1, NTH_VALUE (C0,2) OVER() AS F1, NTH_VALUE (D0,1) OVER() AS G1 FROM
(SELECT damage AS C0, points AS D0, RootQuery_8.id as id_, count(*) over() as cnt_8, max(date_diff) over() as date_diff_8 FROM
(SELECT *, extract(day from date_time - lag(date_time) over (ORDER BY date_time)) as date_diff FROM events WHERE foe_id = ref_.foe_id AND status = 1 AND location_id = ref_.location_id AND date_time < location_id = ref_.date_time ORDER BY date_time DESC LIMIT 15 OFFSET 0)
AS RootQuery_8)
AS BaseQuery8 LIMIT 1) wnd_2
ON wnd_1.id_ <> 0 WHERE cnt_7 >= 10 AND date_diff_7 <= 150 AND cnt_8 >= 10 AND date_diff_8 <= 150) AS layer_1
ON ...
Но результат результатов первого запроса не может быть использован на самом глубоком уровне выбора во втором запросе.
Если запрос выполняется медленно, начните получать план запроса, используя explain(analyze, verbose, buffers, settings)
. Тогда вы увидите, почему это медленно и что нужно улучшить.
@FrankHeikens нет, нет, проблема не в запросе, проблема в том, что мне приходится запускать его 100 раз, чтобы получить нужные мне данные
@nbk, я не пытаюсь выполнить запрос на основе результата другого запроса, а использовать результаты первого запроса в качестве параметра для предложения WHERE во втором, кстати, спасибо за ответ!
TLDR: используйте соединение LATERAL
.
LATERAL
соединения позволяют подзапросам справа ссылаться на столбцы в FROM
элементах слева. Видеть:
Ваш запрос может выглядеть примерно так:
SELECT *, A1+B1-C1-D1-E1-F1+G1+H1 AS A2
FROM (
SELECT character_id, foe_id, location_id, date_time, damage, points FROM events ORDER BY date_time DESC LIMIT 100
) prime
JOIN LATERAL ( -- !
SELECT id_, cnt_7, date_diff_7
, nth_value(A0,1) OVER () AS A1, nth_value(A0,2) OVER () AS B1, nth_value(B0,1) OVER () AS C1, nth_value(B0,2) OVER () AS D1
FROM (
SELECT damage AS A0, points AS B0, RootQuery_7.id AS id_, count(*) OVER () AS cnt_7, max(date_diff) OVER () AS date_diff_7
FROM (
SELECT *, extract(day FROM e.date_time - lag(e.date_time) OVER (ORDER BY e.date_time)) AS date_diff
FROM events e
WHERE e.status = 1
AND e.character_id = prime.character_id -- LATERAL reference
AND e.location_id = prime.location_id -- LATERAL reference
AND e.date_time < prime.date_time -- LATERAL reference
ORDER BY e.date_time DESC
LIMIT 10
) AS RootQuery_7
) AS BaseQuery7
LIMIT 1
) wnd_1 ON wnd_1.id_ <> 0
CROSS JOIN LATERAL ( -- !
SELECT id_, cnt_8, date_diff_8 , nth_value(D0,2) OVER () AS H1, nth_value(C0,1) OVER () AS E1, nth_value(C0,2) OVER () AS F1, nth_value(D0,1) OVER () AS G1
FROM (
SELECT damage AS C0, points AS D0, RootQuery_8.id AS id_, count(*) OVER () AS cnt_8, max(date_diff) OVER () AS date_diff_8
FROM (
SELECT *, extract(day from date_time - lag(date_time) OVER (ORDER BY date_time)) AS date_diff
FROM events
WHERE status = 1
AND foe_id = prime.foe_id -- LATERAL reference
AND location_id = prime.location_id -- LATERAL reference
AND date_time < prime.date_time -- LATERAL reference
ORDER BY date_time DESC
LIMIT 15
) RootQuery_8
) BaseQuery8
LIMIT 1
) wnd_2
WHERE wnd_1.cnt_7 >= 10
AND wnd_1.date_diff_7 <= 150
AND wnd_2.cnt_8 >= 10
AND wnd_2.date_diff_8 <= 150;
Конечно, можно еще упростить. Но это выходит за рамки данного вопроса.
Два экземпляра LIMIT 1
без ORDER BY
приводят к произвольным результатам. Вероятно, следует исправить (или удалить).
В сторону:
По возможности избегайте идентификаторов в смешанном регистре в Postgres. Видеть:
Большое спасибо, ваш ответ - чистое золото, именно то, что мне нужно! причина этого «LIMIT 1» в запросе Windows заключается в том, что он возвращает 10 строк с одинаковым выводом.
.сделайте что-нибудь МИЛОЕ, чтобы вы могли получить доступ к результатам запросов