Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.10.2024, 16:41   #1
llkate_s
 
Регистрация: 19.10.2024
Сообщений: 5
По умолчанию Оптимизация sql запроса SELECT

Здравствуйте! Представлена часть sql запроса с временными таблицами. Сначала формируются таблицы sent, deliv , undeliv. И в конце в итоговой таблице "res" , которая объединяет в себе эти три таблицы, считается количество записей в этих таблицах.
1. Можно ли эти таблицы как-то объединить в целях оптимизации? Они между собой отличаются только по одному условию a.response_test.
2. Насколько сильно влияет на скорость обработки запроса объединение по двум полям одной таблицы с идентичными полями другой таблицы? Например, "left join sent t11 on t11.task_id = t1.task_id AND t1.person_pin = t11.person_pin"
3. Как можно вывести все поля таблицы res с сортировкой по полям более оптимально, не создавая новый запрос?(см последний запрос). Можно ли последний запрос в "res" "впихнуть"?:


sent as

(select distinct a.task_id, a.person_pin, 'sent' as sent
from com.responses a
join all_cont b on a.task_id = b.task_id AND a.person_pin = b.person_pin
and a.status = 'sent' and a.response_test >= current_date-20
),

deliv as

(select distinct a.task_id, a.person_pin, 'deliv' as deliv
from com.responses a
join all_cont b on a.task_id = b.task_id AND a.person_pin = b.person_pin
and a.status = 'deliv1' and a.response_test >= current_date-20
),

undeliv as

(select distinct a.task_id, a.person_pin, 'undeliv' as undeliv
from com.responses a
join all_cont b on a.task_id = b.task_id AND a.person_pin = b.person_pin
and a.status not in ('deliv1','sent') and a.response_test >= current_date-20
),

res as

(select t1.contact_dt, t1.camp, t1.sender_email, t1.contact_status, t1.test,
count(t1.task_id) as planned,
count(t11.task_id) as sent, count(t2.deliv) as deliv,
count(t3.undeliv) as undeliv, count(t4.read) as read
from all_cont t1
left join sent t11 on t11.task_id = t1.task_id AND t1.person_pin = t11.person_pin
left join deliv t2 on t2.task_id = t1.task_id AND t1.person_pin = t2.person_pin
left join undeliv t3 on t3.task_id = t1.task_id AND t1.person_pin = t3.person_pin
group by t1.contact_dt, t1.camp, t1.sender_email, t1.contact_status, t1.test
)

select *
from res order by contact_dt desc, camp, draft_id,contact_status, test
llkate_s вне форума Ответить с цитированием
Старый 20.10.2024, 10:00   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,543
По умолчанию

Код:
select t1.contact_dt, t1.camp, t1.sender_email, t1.contact_status, t1.test,
count(distinct task_id), count(distinct sent_id), count(distinct deliv_id), count(distinct undeliv_id)
-- и добавляем счет по различным person_pin
from all_cont t1
left join (  select a,task_id, a.person_pin, 
            -- делаем ОТДЕЛЬНЫЕ поля для task_id в разных статусах
            case when a.status ='sent' then a.task_id else null end as sent_id, 
            case when a.status ='deliv' then a.task_id else null end as deliv_id,
            case when a.status in ('sent', 'deliv') then null else a.task_id end as undeliv_id
           --  и тоже самое (отдельные поля) для person_pin
           .....
            from com.responses a
           ---  мы нигде не пользуемся  cont (убираем join )
            -- join all cont b on a.task_id =b.task_id and a.person_pin =b.person_pin 
            where a.response_date >=current_date -20
           ) stat on stat.task_id =t1.task_id and stat.person_pin =stat.person_id 
group by t1.contact_dt, t1.camp, t1.sender_email, t1.contact_status, t1.test
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 20.10.2024, 17:18   #3
llkate_s
 
Регистрация: 19.10.2024
Сообщений: 5
По умолчанию

Спасибо Вам большое за помощь!

А здесь «count(distinct task_id), count(distinct sent_id), …» не нужно в скобках указывать таблицу? Вот так:

«count(distinct t1.task_id), count(distinct t11.send_id), …»

И затем джойны в конце указать?
«…
left join sent t11 on t11.task_id = t1.task_id AND t1.person_pin = t11.person_pin
…..»

Не совсем понятно, как выбирается поле нужной нам таблицы
llkate_s вне форума Ответить с цитированием
Старый 20.10.2024, 18:38   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,543
По умолчанию

имя таблцы требуется в случае повтора имен в используемых таблицах, здесь этого нет..
мы используем уникальные имена (точнее алиасы ) sent_id, deliv_id, undeliv_id, ... .
p.s. по крайней мере в моем варианте.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 20.10.2024 в 18:41.
evg_m вне форума Ответить с цитированием
Старый 20.10.2024, 20:08   #5
llkate_s
 
Регистрация: 19.10.2024
Сообщений: 5
По умолчанию

Не знаю как, но результаты сошлись, на 3 минуты быстрее провелся запрос))
Спасибо
llkate_s вне форума Ответить с цитированием
Старый 23.10.2024, 19:15   #6
llkate_s
 
Регистрация: 19.10.2024
Сообщений: 5
По умолчанию

Здравствуйте! Возник еще один небольшой вопрос по тому же запросу. Допустим, вместо условия "a.status not in ('deliv1','sent')" в третьей временной таблице "undeliv" будет условие с подзапросом "b.task_id NOT IN (SELECT task_id FROM deliv)". То есть в данном подзапросе идет обращение к одной из временных таблиц. Как в данном случае будет лучше прописать это в запросе? Если прописать саму временную таблицу deliv, то грузит 10 минут....
llkate_s вне форума Ответить с цитированием
Старый 23.10.2024, 21:55   #7
llkate_s
 
Регистрация: 19.10.2024
Сообщений: 5
По умолчанию

evg_m, Здравствуйте! Возник еще один небольшой вопрос по тому же запросу. Допустим, вместо условия "a.status not in ('deliv1','sent')" в третьей временной таблице "undeliv" будет условие с подзапросом "b.task_id NOT IN (SELECT task_id FROM deliv)". То есть в данном подзапросе идет обращение к одной из временных таблиц. Как в данном случае будет лучше прописать это в запросе? Если прописать саму временную таблицу deliv, то грузит 10 минут....
llkate_s вне форума Ответить с цитированием
Старый 24.10.2024, 09:25   #8
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,543
По умолчанию

может быть так
Код:
select ...,
case ... ,
undeliv.task_id as undeliv_id-- без всяких условий 
from com_responsed a
left join ( -- эквивалент b.task_id not in (select task_id from deliv) 
              select b.task_id from ... as b 
              left join deliv ob b.task_id  =deliv.task_id
              where deliv.task_id is null 
            ) as undeliv
хотите точнее давайте полный ВАШ код (в моем коде нигде нет таблицы b)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 24.10.2024 в 09:28.
evg_m вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Оптимизация запроса nactyx SQL, базы данных 4 08.08.2019 10:56
Оптимизация запроса. EnMac SQL, базы данных 20 15.04.2015 15:11
Оптимизация запроса not in (select ... sanich_23 SQL, базы данных 6 07.11.2014 02:56
Оптимизация запроса stalsoft SQL, базы данных 0 05.07.2011 14:51
Оптимизация SQL запроса Phantom SQL, базы данных 4 24.09.2009 16:07