powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Сложный запрос
38 сообщений из 38, показаны все 2 страниц
Сложный запрос
    #39463385
Всем привет, большая проблема, очень нужна помощь((
Есть база пациентов, случаев очень много, на данный момент 5 миллионов, ну и каждый месяц естественно добавляются новые. Задача в том, что нужно выбрать повторные случаи, то есть, если один и тот же человек с одним полисом посещал несколько раз медицинское учреждение, ну и плюс кое-какие условия, типа совпадает специальность врача, цель посещения и т.д, то тогда эти случаи нужно отобрать. В базе есть разные таблицы, основная - случай лечения, которая соединяется с таблицей пациентов. Один и тот же человек может быть в таблице пациентов под несколькими id.
Проблема в том, что когда там много записей процедура, отбирающая эти случаи отрабатывает ооооочень долго. Ну естественно, потому что таблица объединяется сама с собой... Как быть в такой ситуации? Может быть у кого-то было что-то похожее? Каким образом можно попытаться ускорить? Дайте совет пожалуйста (
...
Рейтинг: 0 / 0
Сложный запрос
    #39463390
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут нужен программист, освоивший язык SQL до слов GROUP BY и HAVING.
А соединять таблицу с собой при этом совсем не нужно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463396
Dimitry Sibiryakov, нельзя просто сгруппировать по номеру полису и взять >1. Одно из условий на дату посещения, если больше 15 дней, то повторным уже не считается
...
Рейтинг: 0 / 0
Сложный запрос
    #39463398
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заянельзя
Можно.

Кареглазая_заяесли больше 15 дней, то повторным уже не считается
А если было четыре посещения с периодом в две недели каждое, это как считается?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463400
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая> нельзя

Зачем спорить, если элементарно не хватает квалификации?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463401
Dimitry Sibiryakov, все 4 должны быть отобраны. Первый потому что у него есть второе посещение и разница дней между ними не больше 15, у второго третье, у третьего четвертое
...
Рейтинг: 0 / 0
Сложный запрос
    #39463406
Гаджимурадов Рустам, я не спорю. А говорю, что обычной группировкой тут не обойдешься
...
Рейтинг: 0 / 0
Сложный запрос
    #39463412
Вот примерная структура
r_pacient : id, polis, dr
r_schet : id, id_type
r_sl : id, id_schet, id_r_pacient, dt_end, mkb, pos, nomlpu

Выбрать r_schet.id, r_sl.id , r_sl.nomlpu, такие, что
возраст (r_pacient.dr) < 65
посещения (r_sl.dt_end)между двумя случаями <16
исключить r_sl.mkb на букву O, r_schet.id_type 1, пары с r_sl1.pos = 2 , а r_sl2.pos =1, если r_sl1.dt_end < r_sl2.dt_end

Помогите пожалуйста тогда написать запрос!
...
Рейтинг: 0 / 0
Сложный запрос
    #39463421
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select .... from r_sl rsl1 join r_schet on ... join r_pacient on ...
where
current_date - r_pacient.dr < 65*365 and
mkb not starting with 'O' and
r_schet.id_type <> 1 and
exists (select * from r_sl rsl2 where rsl2.id_r_pacient = rsl1.id_r_pacient and
    abs(rsl1.dt_end-rsl2.dt_end)<16 and
    (rsl1.dt_end > rsl2.dt_end or (rsl2.pos = 2 and rsl1.pos = 1)))


Как-то так.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463441
Dimitry Sibiryakov, как-то так я сейчас и делаю. Правда соединять надо не по id_r_pacient, а по полису. Но таблица r_sl очень большая, можно ли каким-нибудь образом exists заменить?
...
Рейтинг: 0 / 0
Сложный запрос
    #39463442
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я бы вообще запросом не делал, а набросал ХП, в которой
можно было бы спокойно учесть все предикаты, нюансы и
перламутровые пуговицы, которые через неделю всплывут.
Заодно подзапроса можно будет выкинуть, одного цикла хватит.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463443
Гаджимурадов Рустам, ХП - хранимая процедура?
...
Рейтинг: 0 / 0
Сложный запрос
    #39463446
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заятаблица r_sl очень большая, можно ли каким-нибудь образом exists заменить?Я бы в 1-ю очередь обратил внимание на join'ы - они по-умолчанию inner, если я не ошибаюсь.
Если есть возможность, лучше заменять их на left/right [outer] join'ы - они работают "в один проход" при чем "с нужной стороны", в отличие от inner.
Например, если к основной таблице чз left join присоединить другую с записями по ключу - такое соединение пройдет наиболее безболезненно по времени.

Что касается exists - он работает быстро, ведь он в WHERE и не участвует в соединении таблиц, а только в фильтрации результата.
Можно попробовать и приджойнить "себя же" и в WHERE только даты сравнивать, но я очень сомневаюсь, что будет быстрее.

Да, еще, основное условие "mkb not starting with 'O'" ужасно, по полю mkb с таким условием индекс сомневаюсь, что получится использовать.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463448
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, а долго будет в любом случае, т.к. условия идут по второстепенным таблицам, а значит наверняка перебираются все записи основной большой таблицы не по индексу.

Чтобы хоть часть отсечь в таком случае - придется основной таблицей делать пациентов - их можно по возрасту по индексу фильтрануть.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463467
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockЕсли есть возможность, лучше заменять их на left/right [outer] join'ы - они работают "в один проход" при чем "с нужной стороны", в отличие от inner.
Например, если к основной таблице чз left join присоединить другую с записями по ключу - такое соединение пройдет наиболее безболезненно по времени.

А давай ты не будешь говорить о том в чём совсем не смыслишь. Оба твоих сообщения полнейшая чушь
...
Рейтинг: 0 / 0
Сложный запрос
    #39463517
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяОдин и тот же человек может быть в таблице пациентов под несколькими id.
Бардак.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463615
Фотография Gallemar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanКареглазая_заяОдин и тот же человек может быть в таблице пациентов под несколькими id.
Бардак.
Надо Дока звать, он предметную часть знает.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463629
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заякак-то так я сейчас и делаю.
Тогда в полный рост встаёт вопрос планов, статистики, наличия индексов и прочий высший
пилотаж. Раз уж хитроподвывернутые условия так криво ложатся на схему БД.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сложный запрос
    #39463643
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GallemarНадо Дока звать
не надо, "я еще не волшебник..." © :)

С wadman согласен на 146%, бардак полнейший. Полис ОМС у россиянина один на всю жизнь. А тут ТС даже структуры базы нормально показать не может. Трудно ей будет у нас ;)
...
Рейтинг: 0 / 0
Сложный запрос
    #39463648
pastor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Код: sql
1.
2.
3.
4.
select полис, специализация, count(*), min(Дата), max(Дата)
from Посещения
group by полис, специализация
having (max(Дата) - min(Дата)) > 14
...
Рейтинг: 0 / 0
Сложный запрос
    #39463682
Док, сложно, я просто не знаю как объяснить по-нормальному, чтобы и ненужных вещей не говорить и в тоже время суть.
А насчет id пациента, никакого бардака нет. Такую информацию передает Фонд ОМС, а связано с тем, что пациенты выгружаются помесячно - счетами, и соответственно в каждом счете id пациента уникально, а счетов мб много. Такая структура.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463687
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисYuRockЕсли есть возможность, лучше заменять их на left/right [outer] join'ы - они работают "в один проход" при чем "с нужной стороны", в отличие от inner.
Например, если к основной таблице чз left join присоединить другую с записями по ключу - такое соединение пройдет наиболее безболезненно по времени.

А давай ты не будешь говорить о том в чём совсем не смыслишь. Оба твоих сообщения полнейшая чушь
Окей, чушь, но я написал всё это исходя из своего опыта и своего понимания, как это всё работает.

P.S. Ты утверждаешь, что inner и left join'ы -одинаковы по быстродействию, т.е. для сервера работы одинаковое количество для этих двух видов соединения таблиц?
Я считаю, что нет, и left легче, а ты написал - что это полная чушь.
Так вот, повторяю вопрос: "Ты утверждаешь, что inner и left join'ы -одинаковы по быстродействию, т.е. для сервера работы одинаковое количество для этих двух видов соединения таблиц?"
...
Рейтинг: 0 / 0
Сложный запрос
    #39463689
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторПолис ОМС у россиянина один на всю жизнь.
За свою недолгую жизнь я в прошлом году получил уже третий полис. Так шта...
...
Рейтинг: 0 / 0
Сложный запрос
    #39463695
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

твой опыт весьма поверхностный. Я привык доверять оптимизатору и только если меня не устраивает быстродействие, то рассматриваю как можно самостоятельно оптимизировать запрос. Золотое правило не пытаться преждевременно оптимизировать.
И да в случае inner join вариантов выполнения много больше. Оптимизатор может принять лучшее решение и только если он это делает неправильно нужно рассматривать другие варианты.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463702
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисYuRock,
Я привык доверять оптимизатору и только если меня не устраивает быстродействие, то рассматриваю как можно самостоятельно оптимизировать запрос. Золотое правило не пытаться преждевременно оптимизировать.
И да в случае inner join вариантов выполнения много больше. Оптимизатор может принять лучшее решение и только если он это делает неправильно нужно рассматривать другие варианты.
Именно так я и поступаю тоже всегда. Сдесь же ТС обратился с просьбой дать идеи, как попробовать оптимизировать запрос, который выполняется "оооочень долго". Я дал свои советы, исходя из своего опята.

Симонов ДенисОба твоих сообщения полнейшая чушь.

Симонов Дениствой опыт весьма поверхностный.

Тут можешь продолжать и дальше, меня подобные высказывания не трогают.

Только ты ответь: Ты действительно считаешь чушью (как ты и написал), что left легче inner? Или просто у самого чушь вырвалась случайно?
...
Рейтинг: 0 / 0
Сложный запрос
    #39463715
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockсчитаешь чушью (как ты и написал), что left легче inner?
что значит "легче"? "тяжесть" выполнения запроса зависит от плана. left/right приводят к принудительному порядку объединения таблиц. А у inner или неявных join сервер может сам определить порядок объединения таблиц.

Так что да - про "легче" это если не чушь, то собственная терминология, которая далека от реальности. Сравнивать принудительный порядок и произвольный? Да еще учитывая, что планы могут оказаться одинаковыми.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463721
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockЕсли есть возможность, лучше заменять их на left/right [outer] join'ы - они работают "в один проход" при чем "с нужной стороны", в отличие от inner.
например, вот это чушь. То есть, inner работает "в два прохода", что-ли? Одинаково они работают, просто генерируют разные планы (а иногда и одинаковые). Через left/right ты просто можешь принудительно "задать план", который "работает быстрее".

p.s. про "работает быстрее" - зависит от того, выбирается несколько первых записей, или fetch all. Один и тот же массив записей может выбираться разное время, в зависимости от плана запроса (методов доступа).

рекомендую перечитать
http://www.ibase.ru/dataaccesspaths/

как минимум пункт 3.1
...
Рейтинг: 0 / 0
Сложный запрос
    #39463741
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockСдесь же ТС обратился с просьбой дать идеи, как попробовать оптимизировать запрос, который выполняется "оооочень долго".

Ты план запроса видел? Вполне возможно надо просто где-то индекс создать, может +0, а может и вовсе запрос переписать. А ты свои left join без причины пытаешься воткнуть.

То что starting with не может использовать индекс тоже чушь.

И то что left "легче" inner я действительно считаю чушью.

З.Ы. Тут никто не пытается тебя оскорбить или ущемить твоё самолюбие, но ты действительно не сечёшь фишку. Почитай приведённую kdv статью.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463742
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
insert into TAKE_SL (ID_TAKE, ID_SL, ID_SCHET)
                 select :id_take, sl.ID, sl.id_r_schet
                 from r_sl sl
                 join r_schet s on s.id = sl.id_r_schet and s.status_fin = 1  -- принят к оплате
                 join s_type_schet st on st.id = s.id_type_schet and st.r_typ = 1 and st.typ_omp = 3 and st.id not in (46,48,13,58,59)
                 join r_pacient p on p.id = sl.id_r_pacient and age_person(p.dr,sl.dt_end) < 65

                 join r_pacient p1 on p1.npolis = p.npolis
                 join r_sl sl1 on  sl1.id_r_pacient = p1.id and sl1.id <> sl.id
                                   and sl1.nomlpu = sl.nomlpu and sl1.usl_ok = 3 and sl1.pr_opl = 1
                                   and substring(sl1.ds1 from 1 for 3) = substring(sl.ds1 from 1 for 3)
                                   and sl1.prvs = sl.prvs
                                   and sl1.cel not in ('2','90','91','92','94','11','61','62','63')
                                   and sl1.code_mes1 not in ('RT20','RT21','RT22','RT23','RT24','RT41')
                                   and abs(datediff(day, sl1.dt_end, sl.dt_end)) <16
                                   and iif ((sl.dt_end < sl1.dt_end and sl.type_pos = 2 and sl1.type_pos = 1)
                                             or (sl.dt_end > sl1.dt_end and sl.type_pos = 1 and sl1.type_pos = 2),0,1) = 1
                 where sl.nomlpu =:nomlpu
                       and sl.usl_ok = 3
                       and sl.pr_opl = 1
                       and substring(sl.ds1 from 1 for 1) not in ('C','S','O','Z','Q')
                       and substring(sl.ds1 from 1 for 3) not in ('J00','J01','J02','J03','J04','J05','J06','J07','J08','B18','J35',
                                                                  'N11','N18','N19','N20','T14','B00','B01','B02','B02','B03','B04',
                                                                  'B05','M01','M02','M03','M04','M05','M06','M07','M08','M09','M10',
                                                                  'L50','N80','N81','N82','N83','N84','N85','N86','N87','N88','N89',
                                                                  'N90','N91','N92','N93','N94','N95','N96','N97','N98')
                       and sl.prvs not in(28,263,126,91,258,115,80,17,1,206)
                       and sl.cel not in ('2','90','91','92','94','11','61','62','63')
                       and sl.code_mes1 not in ('RT20','RT21','RT22','RT23','RT24','RT41')
                       and (not exists(select 1 from xml_foms_sl fe where fe.id_sl = sl.id))
                       and (not exists (select first 1 1 from r_oe_sl oesl where oesl.id_sl = sl.id))
                       and (not exists (select first 1 1 from fines f where f.id_sl = sl.id and f.cod_type_exp > 0))
                       and (not exists (select first 1 1 from take_sl tsl_t where tsl_t.id_sl = sl.id and tsl_t.id_take  <> :id_take ))

                       and (not exists(select 1 from xml_foms_sl fe1 where fe1.id_sl = sl1.id))
                       and (not exists (select first 1 1 from r_oe_sl oesl1 where oesl1.id_sl = sl1.id))
                       and (not exists (select first 1 1 from fines f1 where f1.id_sl = sl1.id and f1.cod_type_exp > 0))
                       and (not exists (select first 1 1 from take_sl tsl_t1 where tsl_t1.id_sl = sl1.id and tsl_t1.id_take <> :id_take));


На данный момент вот такой запрос, он отрабатывает быстрее чем с exists, но совсем неправильно
Например
один человек сходил 3 раза в поликлинику, 28.03 - sl.id = 1, 10.04 -sl.id = 2, 13.04 - sl.id = 3. Запрос отрабатывает таким образом, что в результате находятся пары 1 - 2, 2 - 3. То есть вместо трех отбираются четыре 1,2,2,3. Это можно как-то исправить?
...
Рейтинг: 0 / 0
Сложный запрос
    #39463747
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

версия сервера какая?
...
Рейтинг: 0 / 0
Сложный запрос
    #39463766
Симонов Денис, 2.1.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463771
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvнапример, вот это чушь. То есть, inner работает "в два прохода", что-ли? Одинаково они работают, просто генерируют разные планы (а иногда и одинаковые). Через left/right ты просто можешь принудительно "задать план", который "работает быстрее".
Как минимум я отключаю работу оптимизитора (для этого момента), а так же страхуюсь от его возможных ошибок.
Кстати, сейчас провел некоторые тесты своих запросов 14-летней давности на тройке, поменял LEFT на INNER. И, да, план и быстродействие оказались одинаковыми. В то время такого щастья не было, отсюда и привычка "заранее отсекать неверный план".
Вот честно, мне сейчас очень сложно будет перестроиться и НЕ писать LEFT там, где я уверен, что он будет оптимален.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463781
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

не ну 14 лет назад оптимизатор был так себе. Сейчас намного лучше.
...
Рейтинг: 0 / 0
Сложный запрос
    #39463783
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисТы план запроса видел? Вполне возможно надо просто где-то индекс создать, может +0, а может и вовсе запрос переписать. А ты свои left join без причины пытаешься воткнуть.
Как оказалось, версия 2.1, а на ней оптимизатор еще не тот, что сейчас. План, конечно, смотреть надо.

Симонов ДенисТо что starting with не может использовать индекс тоже чушь.

Ты цитируешь то, что я НЕ писал. Я писал:
" not starting with"

а так же
"индекс сомневаюсь, что получится использовать".

Симонов ДенисИ то что left "легче" inner я действительно считаю чушью.
Возможно сейчас, когда оптимизатор стал достаточно хорош, это и так. А раньше план мог измениться в "неправильную сторону" просто при накоплении данных в базу, и приходилось его "направлять", и поэтому лучше было сразу так делать.

Симонов ДенисЗ.Ы. Тут никто не пытается тебя оскорбить или ущемить твоё самолюбие
Это я понимаю прекрасно, тут все на нервах постоянно)
...
Рейтинг: 0 / 0
Сложный запрос
    #39463790
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockСимонов ДенисТо что starting with не может использовать индекс тоже чушь.

Ты цитируешь то, что я НЕ писал. Я писал:
" not starting with"

а так же
"индекс сомневаюсь, что получится использовать".

Уже и не сомневаюсь. Проверил только что на 3.0.1, который у меня в продакшене:
Код: sql
1.
2.
3.
SELECT * FROM COMMANDS C
WHERE NOT C.COMMAND_ID STARTING WITH 'O'
--WHERE C.COMMAND_ID STARTING WITH 'O'


Планы такие:
PLAN (C NATURAL)
и если NOT убрать:
PLAN (C INDEX (PK_COMMANDS))

есть PRIMARY KEY (COMMAND_ID),
COMMAND_ID CHAR(4) NOT NULL
...
Рейтинг: 0 / 0
Сложный запрос
    #39463793
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

not я проглядел, там в принципе индекс проблематично использовать
...
Рейтинг: 0 / 0
Сложный запрос
    #39463826
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Мда, тут уже проще выполнить в процедуре наиболее простой запрос с этими страшными условиями, отстртировав по "НомеруПолиса,Дате", и затем в цикле инсертить, если надо. Так хотя бы наглядно будет.
Другое дело, как в процедуру эти условия передавать трёхэтажные.. Их лучше в отдельной таблице хранить - как "настройки отчета".
...
Рейтинг: 0 / 0
Сложный запрос
    #39463886
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисне ну 14 лет назад оптимизатор был так себе. Сейчас намного лучше."Так себе" только по сравнению с новым. Работал и ладно.
Всегда как-то хватало псевдо-хинтов, да и то нечасто.
Вот чтобы LEFT приходилось писать - это только когда с процедурой соединение, других случаев не припоминаю.
...
Рейтинг: 0 / 0
38 сообщений из 38, показаны все 2 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Сложный запрос
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]