Можем ли мы использовать функцию разделения по окну для запроса ниже

У меня есть запрос, как показано ниже. Могу ли я использовать разбиение по оконной функции вместо группировки и объединения? я должен изменить имя партнера и номер партнера. Также на основе номера партнера меняется одна группа по полю. мой temptable содержит около 24 миллионов записей. я работаю над улучшением производительности этого запроса. в настоящее время выполнение моей хранимой процедуры занимает около 1 часа.

INSERT INTO #FinalResultTable      
 (     
  [F1],              
    [F2],   
    [F3],              
    [F4],                  
    [Partner #],  
    [Partner Name],          
    [F5],              
    [F6],    
    [F7],              
    [F8],                
    [Partner Amount (rounded)]    
    ,[Entity Name]
    ,[Investment Number]
    )      

 SELECT   
    [F1],              
    [F2],   
    [F3],              
    [F4],                  
    -2 as [Partner #],      
 'Work Paper Total' 
    AS [PartnerName],   -- VARCHAR  
    [F5],              
    [F6],    
    [F7],              
    [F8],     
   MAX([WorkPaperTotal]) 
    , [Entity Name]
    ,[Investment Number]
  FROM #FinalResultTable   
  WHERE [Partner #] > 0   
 GROUP BY       
   [F1],              
    [F2],   
    [F3],              
    [F4],   
   [F5],              
    [F6],    
    [F7],              
    [F8], 
    [Entity Name],
    [Investment Number]                

     union all
     SELECT         


    [F1],              
    [F2],   
    [F3],              
    [F4],                 
  -3 as  [Partner #],      

       'Partner Total' 
     AS [PartnerName],   -- VARCHAR  
     [F5],              
    [F6],    
    [F9],              
    [F10],         

  MAX([WorkPaperTotal]) -SUM([Partner Amount (rounded)]) 

    , [Entity Name]
    ,[Investment Number]
  FROM #FinalResultTable   
  WHERE [Partner #] > 0   
 GROUP BY       
    [F1],              
    [F2],   
    [F3],              
    [F4],   
   [F5],              
    [F6],    
    [F9],              
    [F10], 
    [Entity Name],
    [Investment Number]   

пожалуйста, дайте свое предложение, чтобы улучшить производительность этого запроса.

Примеры данных, желаемые результаты и объяснение логики помогут.

Gordon Linoff 18.03.2019 22:35

Вы фактически дублируете данные, чтобы получить разные суммы. т.е. строка #FinalResultTable входит как в агрегаты, так и в группу агрегатов по разным столбцам. Так что нет, вам нужно UNION ALL и вам нужна агрегация. Вы не можете изменить запрос и получить тот же результат.

Thorsten Kettner 18.03.2019 22:43

Рассмотрите возможность использования таблиц в памяти и/или индексов columnstore, если вы собираетесь выполнять много такого рода агрегирования временных данных.

Jeroen Mostert 18.03.2019 22:50

@GordonLinoff у нас есть 3 разных типа партнеров. номера партнеров будут -1,-2 и -3. на основе этого номера партнера расчет суммы партнера будет другим. Также будет другим имя партнера. Раньше он использовал цикл while. но это заняло больше времени, так как у него есть 3 разных вставки. я пытался удалить его с объединением всех. это немного улучшило производительность. еще не много. я работаю над улучшением производительности. но я новичок в работе с базой данных. Есть 24 миллиона записей. это занимает 1,5 часа сейчас.

vinton 19.03.2019 16:03

@ThorstenKettner, как мы можем это сделать? Извините, как упоминалось в комментарии выше, я новичок в работе с базами данных. до того, как он использовал цикл while, который будет вставлять данные три раза. но вставка данных занимала время. поэтому я подумал о том, чтобы избежать этого, используя одиночную вставку.

vinton 19.03.2019 16:05

@JeroenMostert Я понятия не имею о таблице в памяти и индексе столбца, я буду искать ее. если у вас есть пример, не могли бы вы поделиться

vinton 19.03.2019 16:06
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
6
55
1

Ответы 1

Я упрощаю запрос. У вас есть такие данные:

F1 | F7 | F9 | WorkPaperTotal | PartnerAmount
---+----+----+----------------+--------------
1  | 1  | 1  |           1000 |            10
1  | 1  | 2  |           2000 |            20
1  | 2  | 1  |           3000 |            30
1  | 2  | 2  |           4000 |            40
2  | 1  | 1  |           5000 |            50

И вы хотите результат для

select f1, f7 as f, max(workpapertotal) as result, -2 as partner
from mytable
group by f1, f7
union all
select f1, f9 as f, max(workpapertotal) - sum(partneramount) as result, -3 as partner
from mytable
group by f1, f9;

Первая часть дает вам:

F1 | F | result | partner
---+---+--------+--------
1  | 1 |   2000 |      -2
1  | 2 |   4000 |      -2
2  | 1 |   5000 |      -2

Вторая часть дает вам:

F1 | F | result | partner
---+---+--------+--------
1  | 1 |   2960 |      -3
1  | 2 |   3940 |      -3
2  | 1 |   4950 |      -3

Которые делают окончательный результат

F1 | F | result | partner
---+---+--------+--------
1  | 1 |   2000 |      -2
1  | 1 |   2960 |      -3
1  | 2 |   4000 |      -2
1  | 2 |   3940 |      -3
2  | 1 |   5000 |      -2
2  | 1 |   4950 |      -3

(где F означает F7 для партнера -2 и F9 для партнера -3). Из пяти строк таблицы получается шесть строк результата, несмотря на агрегацию. Таким образом, подход, который вы уже используете для объединения двух запросов, уже является единственным возможным подходом. Я предполагаю, что ваше предложение where (WHERE [Partner #] > 0) не исключает очень много строк, поэтому большая часть данных таблицы должна быть прочитана и отсортирована, а затем сгруппирована для агрегирования. И это должно произойти даже дважды. Это требует времени. Вы мало что можете с этим поделать. Купить оборудование было бы моей первой идеей.

Вы можете попробовать следующие индексы, чтобы предоставить предварительно отсортированные данные. Это предложение СУБД, которое она может принять или не принять для запроса.

CREATE INDEX idx1
ON #FinalResultTable(f1,f2,f3,f4,f5,f6,f7,f8,[Entity Name],[Investment Number])
WHERE [Partner #] > 0;

CREATE INDEX idx2 
ON #FinalResultTable(f1,f2,f3,f4,f5,f6,f9,f10,[Entity Name],[Investment Number])
WHERE [Partner #] > 0;

Другие вопросы по теме