Объединение двух запросов возвращает гораздо больше строк, чем ожидалось? - PullRequest
0 голосов
/ 28 марта 2019

У меня есть два запроса. Они оба возвращают около 60 рядов. Но после присоединения они возвращают 900 строк. Есть ли способ получить 60 рядов при их объединении.

Запрос 1:

SELECT 
    f.id_user,
    f.topup_date,
    f.topup_value,
    LEAD(f.topup_date) OVER (PARTITION BY(f.id_user) ORDER BY f.topup_date DESC),
    f.topup_date::timestamp - LEAD(f.topup_date::timestamp) OVER (PARTITION BY(f.id_user) ORDER BY f.topup_date DESC),
    CASE WHEN f.topup_value >= 20 THEN 'Y' ELSE 'N' end,
    CASE WHEN f.topup_value >= 20 THEN LEAD(f.topup_date) OVER (PARTITION BY (f.id_user) ORDER BY f.topup_date DESC) END
FROM topups AS f

Запрос 2:

SELECT 
    CAST(t2.topup_value as float)/CAST(t1.topup_value as float) 
FROM (
    SELECT 
        t1.id_user,
        t1.topup_value,
        ROW_NUMBER() OVER (PARTITION BY t1.id_user ORDER BY t1.topup_date ) AS rowrank
    FROM topups t1 
) AS t1 
INNER JOIN topups t2 ON t1.id_user=t2.id_user
WHERE t1.rowrank = 1
GROUP BY
    t2.id_user,
    t2.topup_value,
    t2.topup_date,
    t1.topup_value,
    t1.rowrank
ORDER BY 
    t2.id_user,
    t2.topup_date DESC

Зарегистрированный запрос:

SELECT 
    f.id_user,
    f.topup_date,
    f.topup_value,
    LEAD(f.topup_date) OVER (PARTITION BY(f.id_user) ORDER BY f.topup_date DESC),
    f.topup_date::timestamp - LEAD(f.topup_date::timestamp) OVER (PARTITION BY(f.id_user) ORDER BY f.topup_date DESC),
    CASE WHEN f.topup_value >= 20 then 'Y' ELSE 'N' END,
    CASE WHEN f.topup_value >= 20 THEN LEAD(f.topup_date) OVER (PARTITION BY (f.id_user) ORDER BY f.topup_date desc) END,
    CAST(t2.topup_value AS float)/CAST(t1.topup_value AS float) 
FROM (
    SELECT 
        t1.id_user,
        t1.topup_value,
        ROW_NUMBER() OVER (PARTITION BY t1.id_user ORDER BY t1.topup_date ) AS rowrank
    FROM topups t1
) AS t1 
INNER JOIN topups t2 ON t1.id_user = t2.id_user 
INNER JOIN topups f  ON f.id_user = t2.id_user
WHERE t1.rowrank = 1
GROUP BY 
    f.id_user,
    f.topup_date,
    f.topup_value,
    t2.topup_value,
    t1.topup_value,
    t2.id_user,
    t2.topup_date
ORDER BY 
    t2.id_user,
    t2.topup_date DESC, 
    f.id_user,
    f.topup_date DESC

1 Ответ

0 голосов
/ 28 марта 2019

Вы хотите объединить два результата запроса. Для каждой строки в одном результате запроса вы ожидаете найти одну строку в другом результате запроса. Итак, посмотрите на первую строку в первом результате запроса. Похоже, вы хотите объединить его с ровно одной строкой во втором результате запроса. Какой это ряд? Какие столбцы вы сравниваете, чтобы найти эту подходящую строку?

Допустим, это результаты вашего запроса:

col1 | col4 | col7 | col6 | col3
-----+------+------+------+-----
A    | B    |  100 |  110 | E
A    | B    |   19 |   22 | E
F    | G    |   80 |   78 | H
F    | I    |   22 |   12 | J

и

col4 | col2 | col1 | col3 | col8
-----+------+------+------+-----
B    |  333 | A    | E    |   89
B    |  211 | A    | E    |   84
G    |  815 | F    | H    |   77
I    |  639 | F    | J    |   79

Вы хотите некоторый результат, подобный этому:

col1 | col4 | col7 | col6 | col3 | col4 | col2 | col1 | col3 | col8
-----+------+------+------+------+------+------+------+------+-----
A    | B    |  100 |  110 | E     | B    |  333 | A    | E    |   89
A    | B    |   19 |   22 | E     | B    |  211 | A    | E    |   84
F    | G    |   80 |   78 | H     | G    |  815 | F    | H    |   77
F    | I    |   22 |   12 | J     | I    |  639 | F    | J    |   79

но вместо этого вы получаете что-то вроде этого:

col1 | col4 | col7 | col6 | col3 | col4 | col2 | col1 | col3 | col8
-----+------+------+------+------+------+------+------+------+-----
A    | B    |  100 |  110 | E     | B    |  333 | A    | E    |   89
A    | B    |  100 |  110 | E     | B    |  211 | A    | E    |   84
A    | B    |   19 |   22 | E     | B    |  333 | A    | E    |   89
A    | B    |   19 |   22 | E     | B    |  211 | A    | E    |   84
F    | G    |   80 |   78 | H     | G    |  815 | F    | H    |   77
F    | G    |   80 |   78 | J     | I    |  639 | F    | J    |   79
F    | I    |   22 |   12 | H     | G    |  815 | F    | H    |   77
F    | I    |   22 |   12 | J     | I    |  639 | F    | J    |   79

Вы получаете такой результат, потому что вы просто выбрали один столбец для объединения двух результатов запроса (id_user в вашем случае, col1 в моем). Посмотрите на первую строку первого результата запроса выше. Имеет col1 = 'A'. Если я присоединяюсь ко второму результату запроса на col1, то есть две совпадающие строки, потому что второй результат запроса имеет две строки с col1 = 'A'. Я получаю гораздо больше матчей, чем хочу.

Итак, какие столбцы мы хотим сопоставить? В моем примере это col1, col3 и col4. Посмотрите на первую строку первого результата запроса еще раз. Имеет col1 = 'A' and col3 = 'B' and col4 = 'E'. Во втором наборе результатов есть только одна строка, соответствующая col1 = 'A' and col3 = 'B' and col4 = 'E'. Следовательно, мой запрос будет

select *
from (<query 1 here>) q1
join (<query 2 here>) q2 on q2.col1 = q1.col1 and q2.col3 = q1.col3 and q2.col4 = q1.col4;

Или я бы лучше прямо сказал, какие столбцы я хочу видеть в своем результате, и удалил повторяющиеся столбцы:

select q1.col1, q2.col4, q1.col7, q1.col6, q1.col3, q2.col2, q2.col8
from (<query 1 here>) q1
join (<query 2 here>) q2 on q2.col1 = q1.col1 and q2.col3 = q1.col3 and q2.col4 = q1.col4
order by q1.col1, q2.col4, q1.col7;
...