|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Имеется три таблицы, основная и две подчинённые. При этом в приложении необходимо отображать данные из основной и несколько вычисляемых столбцов на основе подчинённых. Примерно так: Таблицы: A - основная, B и C - подчинённые. Код: plaintext 1. 2. 3. 4. 5. 6. 7.
Нужно отобразить в сводной таблице для каждой записи из A:
Код: plaintext 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 00:43 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Ответ зависит от многих факторов, включая версию Firebird, размеры таблиц и т.д. и т.п. Ну и было бы неплохо посмотреть на твои собственные попытки, их планы и статистику. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 01:12 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov Ответ зависит от многих факторов, включая версию Firebird, размеры таблиц и т.д. и т.п. Версия 3.0, таблицы... ну пока небольшие - до десятков тысяч записей. Dimitry Sibiryakov Ну и было бы неплохо посмотреть на твои собственные попытки, их планы и статистику. Например в данный момент таблицы B ещё нет, а для таблицы C есть поле в A, которое обновляется по триггеру при изменении C. Но мне кажется это не совсем правильным решением, особенно для новых условий. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 01:15 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp, а чего не a join b join c ? left по вкусу, в зависимости от наличия записей в b и c соответствующих a. в sql можно по всякому делать. "вложенные запросы" - это обычно от неумения join. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 01:34 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvpМне не код нужен, а направление в котором двигаться. Все направления работоспособны при определённых условиях: 1) Простой JOIN + GROUP. 2) JOIN + DERIVED TABLE с GROUP внутри 3) SUBQUERY 4) Хранимые агрегаты. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 12:12 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Привет. alekcvp Имеется три таблицы, основная и две подчинённые
И все это оформил бы, как VIEW. Основной вопрос - какой должен быть join (left или inner)? Могут ли FK-поля в таблицах B и C принимать значение NULL? Должны ли в результате запроса присутствовать записи из A, ссылки на которые отсутствуют в B и/или C? С уважением, Polesov. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 13:41 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp, скорее всего обычным джойном такое не получится. Агрегаты с разными условиями так не сделать. Можно ещё рассмотреть оконные функции, в них агрегаты настраиваются по условию. Совсем просто - это подзапросы по таблицам B и С. Но может оказаться перепробег, т.е. по одним и тем же данным будет несколько проходов. На первый взгляд это Ваш случай - сумма по таблице B, частичная сумма по таблице B... По-моему, оконные для этого - полная выборка и агрегаты по разным условиям. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 15:07 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov Я бы для таблиц B и С агрегатные вычисления оформил бы в виде CTE, которые заджоинил к таблице A. CTE? Polesov Могут ли FK-поля в таблицах B и C принимать значение NULL? Polesov Должны ли в результате запроса присутствовать записи из A, ссылки на которые отсутствуют в B и/или C? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 17:48 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
kdv а чего не a join b join c ? left по вкусу, в зависимости от наличия записей в b и c соответствующих a. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 17:49 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp, Начни в лоб: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
на нескольких десятках тысяч записей будет отрабатываться очень быстро, по крайней мере, прототип приложения отладишь, а там и новые идеи придут. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 17:52 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov, Что-то типа такого? Код: sql 1. 2. 3. 4. 5. 6.
... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 18:04 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Polesov, Что-то типа такого? Код: sql 1. 2. 3. 4. 5. 6.
Агрегат по В можно делать в одной CTE. Я тут интереса ради смакетировал свое предложение (скрипт под спойлером). /* TABLE A ****************************************/ create table A ( ID integer not null, VAL varchar(32) ); alter table A add constraint PK_A primary key ( ID ); /* TABLE B ****************************************/ create table B ( ID integer not null, ID_A integer not null, SUM1 float, SUM2 float, FIX date ); alter table B add constraint PK_B primary key ( ID ); alter table B add constraint FK_B_A foreign key ( ID_A ) references A ( ID ); create index IDX_B_FIX on B ( FIX ); /* TABLE C ****************************************/ create table C ( ID integer not null, ID_A integer not null, MIN1 float ); alter table C add constraint PK_C primary key ( ID ); alter table C add constraint FK_C_A foreign key ( ID_A ) references A ( ID ); create index IDX_C_MIN1 on C ( MIN1 ); /* VIEW V_ABC *************************************/ create view V_ABC ( ID, VAL, SUM_1, SUM_2, MIN_1 ) as with CTE_B ( ID_A, SUM_1, SUM_2 ) as ( select ID_A, sum( SUM1 ) as SUM_1, sum( SUM2 ) as SUM_2 from B where FIX between '01-JAN-2020' and '31-DEC-2020' group by ID_A ), CTE_C ( ID_A, MIN_1 ) as ( select ID_A, min( MIN1 ) as MIN_1 from C group by ID_A ) select a.ID, a.VAL, cte_b.SUM_1, cte_b.SUM_2, cte_c.MIN_1 from A join CTE_B on ( cte_b.ID_A = a.ID ) join CTE_C on ( cte_c.ID_A = a.ID ) ; /* FILL DATA **************************************/ set term ^ ; execute block as declare variable ID_A integer; declare variable ID_B integer; declare variable ID_C integer; declare variable XX_N integer; begin ID_A = 0; ID_B = 0; ID_C = 0; while ( :ID_A < 100000 ) do begin ID_A = :ID_A + 1; insert into A ( ID, VAL ) values ( :ID_A, 'VAL#' || :ID_A ); XX_N = 0; while ( :XX_N < 5 ) do begin ID_B = :ID_B + 1; insert into B ( ID, ID_A, SUM1, SUM2, FIX ) values ( :ID_B, :ID_A, :ID_B / 0.1, :ID_B / 0.3, '01-JUL-2020' ); XX_N = :XX_N + 1; end XX_N = 0; while ( :XX_N < 7 ) do begin ID_C = :ID_C + 1; insert into C ( ID, ID_A, MIN1 ) values ( :ID_C, :ID_A, :ID_C / 0.7 ); XX_N = :XX_N + 1; end end end ^ set term ; ^ commit; A - 100000 записей. B - 500000 записей. C - 700000 записей. Ну, что сказать, как и ожидалось: inner join - выполняется быстро (select count(*) from V_ABC с inner join ~0.9 sec на Cor-i7 3.6 HGz + SSD ) left join - уш-да-уш ... (( ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:03 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov Агрегат по В можно делать в одной CTE. Я в исходном посте упустил, что в B два ключа для A и суммы, соответственно, считаются по разным. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:06 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Polesov Агрегат по В можно делать в одной CTE. Я в исходном посте упустил... Ну, это уже не столь существенно. А вот если все-же требование на left join , я бы рассмотрел возможность изменения схемы выборки. Уж больно left join в данной схеме тормозной. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:16 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Должны быть все записи из А. Возможна ли ситуация, когда в А есть записи, на которые нет ссылок из С и из B по обеим FK? Если да, то требуется left join, а в моем варианте это, мягко говоря, не очень быстрый вариант. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:34 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov alekcvp Должны быть все записи из А. Возможна ли ситуация, когда в А есть записи, на которые нет ссылок из С и из B по обеим FK? Если да, то требуется left join, а в моем варианте это, мягко говоря, не очень быстрый вариант. В C для каждой записи из A должна быть минимум одна запись, а вот в B - не обязательно, плюс там date between будет, под который может ни одна запись не попадать. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:49 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Изначально предусмотрено что ... Надеюсь, идея и ее плюсы и минусы, понятны. Далее надо смотреть по месту. На мой взгляд, странно иметь в таблице B 2 FK на таблицу A - это безусловное применение let join. Впрочем, сложно что-то советовать, не зная предметной области. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:54 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp плюс там date between будет, под который может ни одна запись не попадать. Это условие на inner/left join не влияет. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 19:55 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov На мой взгляд, странно иметь в таблице B 2 FK на таблицу A - это безусловное применение let join. Впрочем, сложно что-то советовать, не зная предметной области. Хм... чё-то я задумался... возможно стоит таблицу B разбить на две... но всё равно в этих B1 и B2 может не быть записей для A, т.е. никуда от left join не деться. Может как-то индексами помочь? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 20:16 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Polesov На мой взгляд, странно иметь в таблице B 2 FK на таблицу A - это безусловное применение let join. Впрочем, сложно что-то советовать, не зная предметной области. Хм... чё-то я задумался... возможно стоит таблицу B разбить на две... но всё равно в этих B1 и B2 может не быть записей для A, т.е. никуда от left join не деться. Может как-то индексами помочь? А обязательно данные получать в одном рекорд-сете? Может быть, для отображения данных на клиенте, дешевле сделать master-detail? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 20:30 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov А обязательно данные получать в одном рекорд-сете? Может быть, для отображения данных на клиенте, дешевле сделать master-detail? По ТЗ - обязательно... но в таблице A вряд ли будет больше 100000 записей. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 20:43 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp Polesov А обязательно данные получать в одном рекорд-сете? Может быть, для отображения данных на клиенте, дешевле сделать master-detail? По ТЗ - обязательно... Для обеспечения inner join можно рассмотреть вариант создания в B и C фиктивных записей, что бы каждой записи из A было соответствие в B и C, но это уже, на мой взгляд, костыль. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 20:54 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov Для обеспечения inner join можно рассмотреть вариант создания в B и C фиктивных записей, что бы каждой записи из A было соответствие в B и C, но это уже, на мой взгляд, костыль. ИМХО проще тогда сделать эти поля в A и при изменении записей в B и C триггером это поле обновлять... ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 21:25 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
alekcvp, А связь A к B и A к C один к одному? Если нет, то этот способ еще хуже. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 21:28 |
|
Вложенные запросы или как правильно это сделать?
|
|||
---|---|---|---|
#18+
Polesov alekcvp, А связь A к B и A к C один к одному? Если нет, то этот способ еще хуже. Нет, один ко многим. А почему хуже? По триггеру пересчитать одно поле одной записи вроде не должно занимать много времени? Почему всё-таки Left Join так катастрофически влияет на производительность? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.05.2020, 21:58 |
|
|
start [/forum/topic.php?fid=40&msg=39964482&tid=1560343]: |
0ms |
get settings: |
11ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
52ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
72ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 181ms |
0 / 0 |