Jin*_*Kim 6 sql postgresql postgresql-9.1
我正在尝试编写一个SQL查询,该查询返回包含数据的表中的行:
表结构如下:
CREATE TABLE person(
id INT PRIMARY KEY,
name TEXT,
operation TEXT);
Run Code Online (Sandbox Code Playgroud)
我想返回尚未"取消"的所有唯一名称行.如果操作是"插入"或"删除"并且存在具有相同操作的相同名称的另一行,则认为行被"取消".
例如,如果我有以下行
id name operation
1 bob insert
2 bob delete
3 bob insert
Run Code Online (Sandbox Code Playgroud)
前两行相互"取消",因为它们使用相反的操作共享相同的名称.所以查询应该返回第3行.
这是另一个例子:
id name operation
1 bob insert
2 bob delete
3 bob insert
4 bob delete
Run Code Online (Sandbox Code Playgroud)
在这种情况下,行1和2抵消,行3和4抵消.因此查询不应返回任何行.
最后的例子:
id name operation
1 bob insert
2 bob insert
Run Code Online (Sandbox Code Playgroud)
在这种情况下,行1和2不会取消,因为操作不相反.所以查询应该返回两行.
我有以下查询处理前两个方案,但它不处理最终方案.
有没有人对可以处理所有3种情况的查询有任何建议?
SELECT MAX(id),name
FROM person z
WHERE operation IN ('insert','delete')
GROUP BY name
HAVING count(1) % 2 = 1;
Run Code Online (Sandbox Code Playgroud)
一种方法是比较操作计数。由于您还需要获取与 InsertCount - deleteCount 或 InsertCount - deleteCount 相对应的 INSERTS 或 DELETES 数量,并且由于 PostgreSQL 支持窗口函数,您应该能够使用 row_number()。
注意:我还没有对此进行测试,但是根据PostgreSQL 手册第 3 章高级功能,3.5 窗口函数,您可以在内联查询中引用窗口函数
SELECT
id, name
FROM
(
SELECT
row_number() over (partition by p.name, p.operation order by p.id desc) rn ,
id,
p.Name,
p.operation,
operationCounts.InsertCount,
operationCounts.deleteCount
FROM
Person p
INNER JOIN (
SELECT
SUM(CASE WHEN operation = 'insert' then 1 else 0 END) InsertCount,
SUM(CASE WHEN operation = 'delete' then 1 else 0 END) deleteCount,
name
FROM
person
GROUP BY
name ) operationCounts
ON p.name = operationCounts.name
WHERE
operationCounts.InsertCount <> operationCounts.deleteCount) data
WHERE
(rn <= (InsertCount - deleteCount)
and operation = 'insert')
OR
(rn <= (deleteCount - InsertCount)
and operation = 'delete')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1151 次 |
| 最近记录: |