Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Postgres窗口函数和分组异常_Sql_Postgresql_Aggregate Functions_Window Functions - Fatal编程技术网

Sql Postgres窗口函数和分组异常

Sql Postgres窗口函数和分组异常,sql,postgresql,aggregate-functions,window-functions,Sql,Postgresql,Aggregate Functions,Window Functions,我正在尝试组合一个查询,该查询将检索用户在一段时间内的统计数据(损益),作为累积结果 以下是我到目前为止的疑问: SELECT p.name, e.date, sum(sp.payout) OVER (ORDER BY e.date) - sum(s.buyin) OVER (ORDER BY e.date) AS "Profit/Loss" FROM result r JOIN game g ON r.game_id = g.game_id JOIN e

我正在尝试组合一个查询,该查询将检索用户在一段时间内的统计数据(损益),作为累积结果

以下是我到目前为止的疑问:

SELECT p.name, e.date, 
    sum(sp.payout) OVER (ORDER BY e.date)
    - sum(s.buyin) OVER (ORDER BY e.date) AS "Profit/Loss" 
FROM result r 
    JOIN game g ON r.game_id = g.game_id 
    JOIN event e ON g.event_id = e.event_id 
    JOIN structure s ON g.structure_id = s.structure_id 
    JOIN structure_payout sp ON g.structure_id = sp.structure_id
                            AND r.position = sp.position 
    JOIN player p ON r.player_id = p.player_id 
WHERE p.player_id = 17 
GROUP BY p.name, e.date, e.event_id, sp.payout, s.buyin
ORDER BY p.name, e.date ASC
查询将运行。然而,结果有点不正确。原因是一个
事件
可以有多个游戏(不同的
sp.payouts
)。因此,如果一个用户在一个具有不同支付的事件中有两个结果(即,每个事件有4个游戏,一个用户从一个事件中获得20英镑,从另一个事件中获得40英镑),则上述结果将显示为多行

显而易见的解决方案是将
分组修改为:

GROUP BY p.name, e.date, e.event_id
然而,Postgres对此表示不满,因为它似乎没有意识到
sp.payout
s.buyin
在聚合函数中。我得到一个错误:

列“sp.payout”必须出现在GROUP BY子句中或用于 聚合函数

我正在Ubuntu Linux服务器上运行9.1。

我是否遗漏了什么,或者这可能是Postgres中的真正缺陷?

事实上,您使用的是聚合函数,而不是。您正在使用。这就是为什么PostgreSQL要求将
sp.payout
s.buyin
包含在
groupby
子句中

通过附加一个
OVER
子句,聚合函数
sum()
被转换成一个窗口函数,它在保留所有行的同时聚合每个分区的值

您可以组合窗口函数和聚合函数。首先应用聚合。从您的描述中,我不明白您希望如何处理每次活动的多个付款/购买。作为猜测,我计算了每个事件的它们的总和。现在,我可以从
GROUP BY
子句中删除
sp.payout
s.buyin
,并为每个
玩家
事件
获取一行:

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\u id
e.event\u id
在各自的表中是
主键

我将
e.event\u id
添加到
WINDOW
子句的
ORDER BY
,以获得确定的排序顺序。(同一天可能有多个事件。)结果中还包括
event_id
,以区分每天的多个事件

虽然查询仅限于单个玩家(
其中p.player_id=17
),但我们不需要将
p.name
p.player_id
添加到
分组依据
订单依据
。如果其中一个联接将不适当地相乘行,则得到的总和将不正确(部分相乘或完全相乘)。按
p.name进行分组当时无法修复查询

我还从
groupby
子句中删除了
e.date
。主键
e.event\u id
覆盖输入行的所有列

如果将查询更改为一次返回多个玩家,请调整:

...
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.player_id<17——示例——多个玩家
按p.name、p.player\u id、e.date、e.event\u id——e.date和p.name进行分组
窗口w AS(按p.name、p.player\u id、e.date、e.event\u id排序)
按p.name、p.player\u id、e.date、e.event\u id排序;
除非
p.name
被定义为唯一(?),否则按
player_id
进行分组和排序,以获得确定排序顺序的正确结果


我只将
e.date
p.name
保留在
groupby
中,以便在所有子句中具有相同的排序顺序,希望性能有所提高。否则,您可以删除那里的列。(与第一个查询中的
e.date
类似。)

第一个查询正在运行,但是查询的输出没有给出所需的结果。我可以看出什么样的修正案在理论上是可行的,但博士后不喜欢它。我稍后会尝试上面的方法,并让您知道。但是,如果一个“event_id”有多个“payout”金额,那么您的查询输出中似乎会有两行。我刚刚尝试了您建议的修改,它确实返回了多行,其中一个事件id有多个sp.payout值。@马丁:见我的修正答案。您不需要在窗口函数中按p.name、e.event\u id进行
分区,分组才能按预期工作吗?@RyanTuck:有几个未解释/模糊的位。我改进和澄清了(或者至少希望如此)。