我要执行一些有点复杂的SQL查询,而且我不确定正确的策略是什么。
考虑模型:
event
foreignId Int
time UTCTime
success Bool
并假设我有一个谓词,我们可以调用trailingSuccess
,如果最后True
n
为events
,则为success
。我想测试这个谓词。也就是说,我想在event
上运行一个查询,该查询返回foreignId
的计数,event
每个success
都是n
event
} {或更多}记录了SELECT count (*)
FROM (SELECT e.foreignId
FROM event e
...
ORDER BY e.time ASC
LIMIT n)
。
我正在使用Postgres,如果重要的话,但如果可能的话,我宁愿留在ANSI片段中。
计算此查询的合理策略是什么?
到目前为止,我的代码如下:
foreign_id time success
1 14:00 True
1 15:00 True
1 16:00 True
1 17:00 True
2 14:00 False
2 15:00 True
2 16:00 True
2 17:00 True
3 14:00 True
3 15:00 True
3 16:00 True
显然,我没有走得太远。我不确定如何表达一个量化多行的谓词。
对于假设用法,n = 4就可以了。
示例数据:
foreign_id
对于示例数据,查询应返回1,因为有n = 4个成功事件,其中foreign_id = 1. foreign_id
2不计算,因为在最后4个中有一个假值{{1因为没有足够的事件使用foreign_id = 3,所以3不计算。
答案 0 :(得分:2)
尝试找到最新的"不成功"使用简单的foreignID
子句输入每个GROUP BY
的毛发。在子查询中使用它,您可以将它连接回表,计算匹配foreignID
并且有更新时间的记录(对于每个foreignID
)。
类似的东西:
SELECT lastn.foreignID, count(*)
FROM
(SELECT foreignID, MAX(time) AS lasttime
FROM event
WHERE success = 'n'
GROUP BY foreignID
) AS lastn
JOIN event AS e
ON e.foreignID = lastn.foreignID
AND e.time > lastn.lasttime
GROUP BY lastn.foreignID;
您可以尝试使用左连接等来根据需要调整它。
答案 1 :(得分:1)
第一个派生表选择至少包含n个事件的所有foreignIds。子查询检查每个foreignId的最后n个事件是否都成功。
SELECT COUNT(*)
FROM (
SELECT foreignId
FROM event
GROUP BY foreignId
HAVING COUNT(*) >= n
) t1
WHERE (
SELECT COUNT(CASE WHEN NOT success THEN 1 END) = 0
FROM event
WHERE foreignId = t1.foreignId
ORDER BY time DESC
LIMIT n
)
答案 2 :(得分:1)
select count(*)
from (
select
foreignId,
row_number() over(partition by foreignId order by "time" desc) as rn,
success
from event
) s
where rn <= n
group by foreignId
having bool_and(success)
答案 3 :(得分:0)
我最后在sqlfiddle上乱了一会儿,直到我到达这里:
select count (*)
from (select count (last.foreignId) as cnt
from (select foreignId
from event
and success = True
order by time desc
) as last
group by last.foreignId) as correct
where correct.cnt >= 4
我想我所添加的洞察力是每一层“选择”都可以被认为是内部选择的过滤器。