Mar*_*ock 5 sql postgresql ruby-on-rails
我有一个postgres表,看起来像这样:
id | user_id | state | created_at
Run Code Online (Sandbox Code Playgroud)
州可以是以下任何一种:
new, paying, paid, completing, complete, payment_failed, completion_failed
Run Code Online (Sandbox Code Playgroud)
我需要一个返回报告的语句,其中包含以下内容:
到目前为止我有这个:
SELECT
DATE(created_at) AS date,
SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at)
Run Code Online (Sandbox Code Playgroud)
通过将此选项添加到选择中,可以轻松完成正在进行和失败的状态:
SUM(CASE WHEN state IN('new','paying','completing') THEN 1 ELSE 0 END) AS in_progress,
SUM(CASE WHEN state IN('payment_failed','completion_failed') THEN 1 ELSE 0 END) AS failed
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何每天每个user_id只进行一次in_progress,并计算失败的状态.
我需要这个的原因是操纵我们的统计数据中的失败率,因为许多触发失败或不完整订单的用户继续触发更多会使我们的失败率膨胀.
提前感谢你.
尝试类似的方法:
SELECT
DATE(created_at) AS date,
SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid,
COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id ELSE NULL END) AS in_progress,
COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id ELSE NULL END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);
Run Code Online (Sandbox Code Playgroud)
主要思想 -COUNT (DISTINCT ...)将计算唯一值user_id并且不会计算NULL值。
详细信息:聚合函数, 4.2.7。聚合表达式
具有相同样式的整个查询计数并简化CASE WHEN ...:
SELECT
DATE(created_at) AS date,
COUNT(CASE WHEN state = 'complete' THEN 1 END) AS complete,
COUNT(CASE WHEN state = 'paid' THEN 1 END) AS paid,
COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id END) AS in_progress,
COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);
Run Code Online (Sandbox Code Playgroud)