Преобразовать подзапрос в само присоединение - PullRequest
0 голосов
/ 14 февраля 2019

плохо знаком с SQL, и я понимаю, что объединения, как правило, выполняются быстрее, чем подзапросы.У меня есть следующая таблица, и мой текущий запрос дает мне требуемые результаты, но я не могу обернуть голову вокруг аналогичного запроса, который вместо этого использует self join, предполагая, что это возможно.

Таблица

id           scheduled_id action_id
------------ ------------ ------------
1            1            1
2            1            2
3            1            3
4            2            1
5            2            2
6            3            1

Схема

create table ma (
id integer primary key,
scheduled_id integer,
action_id integer
);

insert into ma (
id,
scheduled_id,
action_id
)
values
(1, 1, 1),
(2, 1, 2),
(3, 1, 3),
(4, 2, 1),
(5, 2, 2),
(6, 3, 1);

Запрос

select * from ma where action_id = 3
union all
select * from ma where scheduled_id not in (
  select scheduled_id from ma
  where action_id = 3)

Результат

id           scheduled_id action_id
------------ ------------ ------------
3            1            3
4            2            1
5            2            2
6            3            1

В моем результате должны быть все строки со значением action_id, равным 3 плюсвсе строки для тех запланированных идентификаторов, которые не имеют значения action_id, равного 3.

. sqlfiddle можно найти по адресу http://sqlfiddle.com/#!5/0ba51/3.

Спасибо.

Ответы [ 6 ]

0 голосов
/ 15 февраля 2019
SELECT m1.* 
FROM ma m1
INNER JOIN
(
    SELECT * 
    FROM ma m2 
    WHERE m2.action_id = 3
) AS matbl 
WHERE m1.action_id = 3 
OR matbl.scheduled_id<>m1.scheduled_id

Надеюсь, это поможет.

0 голосов
/ 14 февраля 2019

Результат, который вы ищете с помощью самостоятельного объединения:

SELECT DISTINCT t1.*
FROM ma t1
JOIN ma t2  
ON  t1.SCHEDULED_ID <> t2.SCHEDULED_ID --Satisfies 2nd query
WHERE t2.ACTION_ID = 3 --Satisfies 2nd query
    OR  t1.ACTION_ID = 3 --Satisfies 1st query
ORDER BY t1.ID
0 голосов
/ 14 февраля 2019

Как насчет этого?Хотя не само присоединение, но быстрее, чем объединение

select * from ma
where action_id = 3 or scheduled_id not in (
    select scheduled_id from ma
    where action_id = 3
  )
0 голосов
/ 14 февраля 2019

Этот код работает, только если ваш action_id всегда идет 1,2,3,4 и т. Д. И никогда не пропускает 3. Я просто хотел предоставить альтернативный ответ на случай, если добавление в понятие max (action_id) может быть полезно дляyou.

select ma.id
     , ma.scheduled_id
     , ma.action_id
     , ma_max.max_action_id
from (
    select scheduled_id
         , max(action_id) as max_action_id
    from ma
    group by scheduled_id
) ma_max
join ma
    on ma_max.scheduled_id = ma.scheduled_id 
where (action_id = 3 or max_action_id < 3)

Это почти наверняка не будет работать так же хорошо, как и другие ответы, которые используют "EXISTS".Мне просто нравится, как сложность логики сводится к одной легко читаемой строке в where (action_id = 3 or max_action_id < 3).

0 голосов
/ 14 февраля 2019

Моим результатом должны быть все запланированные значения, которые имеют значение 3, плюс все запланированные значения и action_ids для тех запланированных значений, которые не имеют значения 3.

Это не то, чтоваш запрос делает.Запрос, который делает это:

select ma.*
from ma
where exists (select 1
              from ma ma2
              where ma2.scheduled_id = ma.scheduled_id and
                    ma2.action_id = 3
             );

Несмотря на то, что вы могли бы сделать это с самостоятельным объединением, это сложно, потому что запрос может привести к дублированию.Я рекомендую exists или in для логики.

0 голосов
/ 14 февраля 2019

Я не думаю, что JOIN действительно то, что вам нужно здесь.Я бы использовал следующий запрос, который избегает UNION:

SELECT m.* 
FROM ma m
WHERE 
    m.action_id = 3
    OR NOT EXISTS (
        SELECT 1
        FROM ma m1
        WHERE 
            m1.scheduled_id = m.scheduled_id
            AND m1.action_id = 3
    )

Когда дело доходит до проверки на наличие (или отсутствие) чего-либо, NOT EXISTS с коррелированным подзапросом обычно является наиболее актуальным и эффективным подходом.

...