Вие стене , всъщност, използвайки агрегатни функции. Използвате прозоречни функции . Ето защо 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 в първата заявка.)