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