@Ngswolf

Объединение. Как правильно оформить таблицу?

Из одной таблички нужно несколько раз выбирать данные. При чем сначала, перед всеми этими данными писать название таблицы. Потом некая выборка, потом количество записей по этой выборке. И так далее.
Делаю вот так, все названия и подсчет падают вниз:
select 'Счета юридических лиц'  Балансовый_счет, null Наименование, null  Количество_лицевых_счетов
from z#PL_US
where rownum < 2
union all
(select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where  -- [ЮР. ЛИЦА]
       --кредитные договоры на овердрафты,на транши овердрафтов,договоры на кредитные линии,договоры на транши
      ((c_NUM like '441%' or c_NUM like '442%' or c_NUM like '443%' or c_NUM like '444%' or 
       c_NUM like '445%' or c_NUM like '446%' or c_NUM like '447%' or c_NUM like '448%' or
       c_NUM like '449%' or c_NUM like '450%' or c_NUM like '451%' or c_NUM like '452%' or 
       c_NUM like '443%' or c_NUM like '454%' or c_NUM like '456%') and c_NUM not like '4__15%')
       or
       ((c_NUM like '460%' or c_NUM like '461%' or c_NUM like '462%' or c_NUM like '463%' or 
         c_NUM like '464%' or c_NUM like '465%' or c_NUM like '466%' or c_NUM like '467%' or
         c_NUM like '468%' or c_NUM like '469%' or c_NUM like '470%' or c_NUM like '471%' or
         c_NUM like '472%' or c_NUM like '473%')  and c_NUM not like '4__08%')  
group by c_NUM, c_NAME
union all
select 'Итого по пункту 1.1:', null, count(c_NAME)
from z#PL_US)
union
(select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where  -- [ЮР. ЛИЦА]
       -- депозитные (срочные) договоры 
       (c_NUM like '410%' or c_NUM like '411%' or c_NUM like '412%' or c_NUM like '413%'
        or c_NUM like '414%' or c_NUM like '415%' or c_NUM like '416%' or c_NUM like '417%' 
        or c_NUM like '418%' or c_NUM like '419%' or c_NUM like '420%' or c_NUM like '421%' 
        or c_NUM like '422%' or c_NUM like '425%' or c_NUM like '427%' or c_NUM like '428%'
        or c_NUM like '429%' or c_NUM like '430%' or c_NUM like '431%' or c_NUM like '432%' 
        or c_NUM like '433%' or c_NUM like '434%' or c_NUM like '435%' or c_NUM like '436%' 
        or c_NUM like '437%' or c_NUM like '438%' or c_NUM like '439%' or c_NUM like '440%')
group by c_NUM, c_NAME
union all
select 'Итого по пункту 1.2:', null, count(c_NAME)
from z#PL_US)

cafd8056359a486190d2c5dd8a27deca.png
  • Вопрос задан
  • 322 просмотра
Пригласить эксперта
Ответы на вопрос 5
profit
@profit
Разработка | Оптимизация. Telegram: @evzavyalov
Для Rsa97 Rsa97
Разделите на отдельные запросы, легче будет
Зачем разделять на под-запросы? Если таблица большая будет, то N-ое количество раз тянуть - плохо. Да и легче не будет

И сократите кучу OR'ов на
(c_NUM >= 44100 AND c_NUM < 45700)

и это тоже на мой взгляд ужасное решение. все равно их будет много
лучше такое:
substr(c_NUM,1,3) in ('441', '442', ...)?

------------------

Один раз тянется вся таблица, далее используем полученные данные для вывода.
Разбирайся, улучшай.
select c_NUM
     , cnt
  from (
with tab as (select substr(c_NUM,1,3) c_NUM
                  , count(1) cnt
               from z#PL_US 
              where substr(c_NUM,1,3) in ('441', '442',  ... 
                                         ,'410', '411',  ... 
                                         )
              group by substr(c_NUM,1,3)
             )
    select 1 sort , c_NUM, CNT 
      from tab
     where c_NUM in ('441', '441')

    union

    select 2 sort , c_NUM, CNT 
      from tab
     where c_NUM in ('410', '411', ...)
                
    union
    
    select 3 sort ,'ИТОГО П.1: ', sum(cnt) 
      from tab
     where c_NUM in ('441', '441', ....)
     
    union
    
    select 4 sort ,'ИТОГО П.2: ', sum(cnt) 
      from tab
     where c_NUM in ('410', '411', ...)
     
    order by sort
)
Ответ написан
Vapaamies
@Vapaamies
В творческом кризисе
Помимо исключения or-ов, этот унылый запрос нужно переписать с использованием grouping и rollup, и тогда получится простой запрос без подзапросов и union all.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Апофигей! Да ещё и с ошибками копипасты.
Разделите на отдельные запросы, легче будет. Ну или добавьте поле для явной сортировки строк.
И сократите кучу OR'ов на
(c_NUM >= 44100 AND c_NUM < 45700)
Ответ написан
@Ngswolf Автор вопроса
В общем у меня получилось вот что:
select 'Юридические лица'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all
select 'Кредитные договоры на овердрафты,на транши овердрафтов,договоры на кредитные линии,договоры на транши'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all
select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where  -- [ЮР. ЛИЦА]
       --кредитные договоры на овердрафты,на транши овердрафтов,договоры на кредитные линии,договоры на транши
      (substr(c_NUM,1,3) in ('441', '442', '443', '444', '445', '446', '447', '448', '449', '450', '451', '452', '443', '454', '456') and substr(c_NUM,1,5)<>'4__15%')
       or
      (substr(c_NUM,1,3) in ('460', '461', '462', '463', '464', '465', '466', '467', '468', '469', '470', '471', '472', '473')  and substr(c_NUM,1,5)<>'4__08%') 
group by C_NUM, c_NAME
union all          
select 'Депозитные (срочные) договоры'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all      -- депозитные (срочные) договоры 
select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where    
       substr(c_NUM,1,3) in ('410', '411', '412', '413', '414', '415', '416', '417', '418', '419', '420', '421', '422', '425', '427', '428', '429', '430', '431', '432', '433', '434', '435', '436', '437', '438', '439', '440')
group by (c_NUM, c_NAME)
union all
select 'Договоры РКО, договоры пластиковых карт юридических лиц по каждому виду валют'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all       --договоры РКО, договоры пластиковых карт юридических лиц по каждому виду валют
select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where  
        substr(c_NUM,1,3) in ('401', '402', '403', '404', '405', '406', '407') 
        or substr(c_NUM,1,5) in ('40802', '40804', '40805', '40806', '40807', '40809', '40811', '40812', '40814', '40815', '40818', '40819', '40821', '40901', '40902', '40903', '40907', '40908', '47401', '47402', '47409', '47410')
group by (c_NUM, c_NAME)
union all
select 'Физические лица'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all
select 'Кредитные договоры на овердрафты,договоры на транши овердрафтов,договоры на кредитные линии,договоры на транши'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all
select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where       -- [ФИЗ.ЛИЦА]
       --кредитные договоры на овердрафты,договоры на транши овердрафтов,договоры на кредитные линии,договоры на транши
        substr(c_NUM,1,3) in ('455', '457') and substr(c_NUM,1,5)<>'4__15'
group by (c_NUM, c_NAME)
union all
select 'Депозитные договоры'  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all       --депозитные договоры  
 select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where      
       substr(c_NUM,1,3) in ('423', '426')
group by (c_NUM, c_NAME)

union all
select 'Счета физических лиц '  Балансовый_счет, null Наименование, null   Количество_лицевых_счетов
from  z#PL_US 
where rownum < 2
union all       --Счета физических лиц 
 select c_NUM  Балансовый_счет, c_NAME Наименование, count(c_NAME)  Количество_лицевых_счетов
from z#PL_US 
where        
       substr(c_NUM,1,5) in ('40803', '40810', '40813', '40817', '40820')
group by (c_NUM, c_NAME)
union all
select null Балансовый_счет, 'Итого лицевых счетов:' Наименование, count(c_NAME)
from  z#PL_US 
where  -- [ЮР. ЛИЦА]
       --кредитные договоры на овердрафты,на транши овердрафтов,договоры на кредитные линии,договоры на транши
      substr(c_NUM,1,3) in ('441', '442', '443', '444', '445', '446', '447', '448', '449', '450', '451', '452', '443', '454', '456') and substr(c_NUM,1,5)<>'4__15'
       or
       ( substr(c_NUM,1,3) in ('460', '461', '462', '463', '464', '465', '466', '467', '468', '469', '470', '471', '472', '473')  and  substr(c_NUM,1,5)<>'4__08')  
      -- депозитные (срочные) договоры 
       or
       substr(c_NUM,1,3) in ('410', '411', '412', '413', '414', '415', '416', '417', '418', '419', '420', '421', '422', '425', '427', '428', '429', '430', '431', '432', '433', '434', '435', '436', '437', '438', '439', '440')
       --договоры РКО, договоры пластиковых карт юридических лиц по каждому виду валют
       or 
        substr(c_NUM,1,3) in ('401', '402', '403', '404', '405', '406', '407') 
        or substr(c_NUM,1,5) in ('40802', '40804', '40805', '40806', '40807', '40809', '40811', '40812', '40814', '40815', '40818', '40819', '40821', '40901', '40902', '40903', '40907', '40908', '47401', '47402', '47409', '47410')
        -- [ФИЗ.ЛИЦА]
       --кредитные договоры на овердрафты,договоры на транши овердрафтов,договоры на кредитные линии,договоры на транши
       or
        substr(c_NUM,1,3) in ('455', '457') and substr(c_NUM,1,5)<>'4__15'
       --депозитные договоры  
       or
       substr(c_NUM,1,3) in ('423', '426')
       --Счета физических лиц 
       or 
       substr(c_NUM,1,5) in ('40803', '40810', '40813', '40817', '40820')

Заказчик очень хотел, чтобы были названия каждых пунктов, а тут без union-ов никак
Ответ написан
@AdvanTiSS
Рекомендую для оптимизации создать таблицы групп счетов
c_GROUP(id, description)
и элементов групп
с_GROUP_ITEM(c_GROUP_id, c_NUM)

Наполняем таблицы всевозможными комбинациями групп и получаем красивые и оптимизированные запросы.
Плюс вы получаете большую гибкость построения запроса клиентом.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы