PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Прозоречна функция на Postgres и групиране по изключение

Вие стене , всъщност, използвайки агрегатни функции. Използвате прозоречни функции . Ето защо PostgreSQL изисква sp.payout и s.buyin да бъдат включени в GROUP BY клауза.

Чрез добавяне на OVER клауза, агрегатната функция sum() се превръща в прозоречна функция, която събира стойности на дял, докато запазва всички редове.

Можете да комбинирате функции на прозореца и агрегатни функции . Първо се прилагат агрегации. Не разбрах от вашето описание как искате да се справите с множество изплащания/купувания на събитие. Като предположение изчислявам сума от тях за събитие. Сега Мога да премахна sp.payout и s.buyin от GROUP BY клауза и да получите един ред на player и event :

SELECT p.name
     , e.event_id
     , e.date
     , sum(sum(sp.payout)) OVER w
     - sum(sum(s.buyin  )) OVER w AS "Profit/Loss" 
FROM   player            p
JOIN   result            r ON r.player_id     = p.player_id  
JOIN   game              g ON g.game_id       = r.game_id 
JOIN   event             e ON e.event_id      = g.event_id 
JOIN   structure         s ON s.structure_id  = g.structure_id 
JOIN   structure_payout sp ON sp.structure_id = g.structure_id
                          AND sp.position     = r.position
WHERE  p.player_id = 17 
GROUP  BY e.event_id
WINDOW w AS (ORDER BY e.date, e.event_id)
ORDER  BY e.date, e.event_id;

В този израз:sum(sum(sp.payout)) OVER w , външният sum() е прозоречна функция, вътрешната sum() е агрегатна функция.

Ако приемем p.player_id и e.event_id са PRIMARY KEY в съответните им таблици.

Добавих e.event_id към ORDER BY на WINDOW клауза за достигане до детерминиран ред на сортиране. (Може да има множество събития на една и съща дата.) Включен също event_id в резултата, за да разграничите няколко събития на ден.

Докато заявката се ограничава до единична играч (WHERE p.player_id = 17 ), не е необходимо да добавяме p.name или p.player_id към GROUP BY и ORDER BY . Ако едно от обединяванията умножи редовете ненужно, получената сума ще бъде неправилна (умножена частично или напълно). Групиране по p.name тогава не можах да поправя заявката.

Премахнах и e.date от GROUP BY клауза. Първичният ключ e.event_id обхваща всички колони на входния ред след PostgreSQL 9.1.

Ако променяте заявката, за да върнете няколко играча наведнъж, адаптирайте:

...
WHERE  p.player_id < 17  -- example - multiple players
GROUP  BY p.name, p.player_id, e.date, e.event_id  -- e.date and p.name redundant
WINDOW w AS (ORDER BY p.name, p.player_id, e.date, e.event_id)
ORDER  BY p.name, p.player_id, e.date, e.event_id;

Освен ако p.name е дефиниран уникален (?), групиране и подреждане от player_id освен това, за да получите правилни резултати в детерминиран ред на сортиране.

Запазих само e.date и p.name в GROUP BY да има идентичен ред на сортиране във всички клаузи, надявайки се на полза от производителността. В противен случай можете да премахнете колоните там. (Подобно само за e.date в първата заявка.)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Създаване на потребител с криптирана парола в PostgreSQL

  2. Архивиране/възстановяване на докеризирана PostgreSQL база данни

  3. Добавете интервал към времеви отпечатък с помощта на Ecto Fragments

  4. Преобразувайте името на месеца в номер на месеца в PostgreSQL

  5. Максимален брой знаци в етикетите (имена на таблици, колони и т.н.)