我有一个每个用户的呼叫列表,有时用分钟分隔。用户可以在这些电话中购买或不购买。 当用户在最后一次通话后45分钟内拨打电话时,我需要考虑它与第一次通话时的通话时间相同。
我需要获得最终的呼叫数量(将呼叫分开的时间少于45分钟) 以及每位用户购买东西的电话数量。
例如,我有一个这样的列表:
buyer timestamp bougth_flag
tom 20150201 9:15 1
anna 20150201 9:25 0
tom 20150201 10:15 0
tom 20150201 10:45 1
tom 20150201 10:48 1
anna 20150201 11:50 0
tom 20150201 11:52 0
anna 20150201 11:54 0
决赛桌将是:
buyer time_started calls articles_bought
tom 20150201 9:15 1 1
anna 20150201 9:25 1 0
tom 20150201 10:15 3 2
anna 20150201 10:50 2 0
tom 20150201 11:52 1 0
因此,我需要合并分隔少于45分钟的行,并按用户分开。 这很容易用循环,但我没有在我使用的postgresql中的循环或函数/过程。 关于如何做的任何想法?
谢谢
答案 0 :(得分:1)
最大的问题是你需要每45分钟对结果进行分组,这使得它变得棘手。这个查询是一个很好的起点,但它并不完全正确。它可以帮助你开始:
SELECT a.buyer,
MIN(a.timestamp),
COUNT(a),
COUNT(b),
SUM(a.bougth_flag),
SUM(b.bougth_flag)
FROM calls a
LEFT JOIN calls b ON (a.buyer = b.buyer
AND a.timestamp != b.timestamp
AND a.timestamp < b.timestamp
AND a.timestamp + '45 minutes'::INTERVAL > b.timestamp)
GROUP BY a.buyer,
DATE_TRUNC('hour', a.timestamp) ;
结果:
┌───────┬─────────────────────┬───────┬───────┬─────┬─────┐
│ buyer │ min │ count │ count │ sum │ sum │
├───────┼─────────────────────┼───────┼───────┼─────┼─────┤
│ tom │ 2015-02-01 11:52:00 │ 1 │ 0 │ 0 │ Ø │
│ anna │ 2015-02-01 11:50:00 │ 2 │ 1 │ 0 │ 0 │
│ anna │ 2015-02-01 09:25:00 │ 1 │ 0 │ 0 │ Ø │
│ tom │ 2015-02-01 09:15:00 │ 1 │ 0 │ 1 │ Ø │
│ tom │ 2015-02-01 10:15:00 │ 4 │ 3 │ 2 │ 3 │
└───────┴─────────────────────┴───────┴───────┴─────┴─────┘
答案 1 :(得分:1)
由于您事先并不知道“通话”将持续多长时间(您可以在一整天内每隔30分钟接听一位买家的电话 - 请参阅提问评论),您只能通过递归解决此问题CTE。 (注意我将您的列'时间戳'更改为'ts'。从不使用关键字作为表名或列名。)
WITH conversations AS (
WITH RECURSIVE calls AS (
SELECT buyer, ts, bought_flag, row_number() OVER (ORDER BY ts) AS conversation, 1::int AS calls
FROM (
SELECT buyer, ts, lag(ts) OVER (PARTITION BY buyer ORDER BY ts) AS lag, bought_flag
FROM list) sub
WHERE lag IS NULL OR ts - lag > interval '45 minutes'
UNION ALL
SELECT l.buyer, l.ts, l.bought_flag, c.conversation, c.calls + 1
FROM list l
JOIN calls c ON c.buyer = l.buyer AND l.ts > c.ts
WHERE l.ts - c.ts < interval '45 minutes'
)
SELECT buyer, ts, bought_flag, conversation, max(calls) AS calls
FROM calls
GROUP BY buyer, ts, bought_flag, conversation
order by conversation, ts
)
SELECT buyer, min(ts) AS time_started, max(calls) AS calls, sum(bought_flag) AS articles_bought
FROM conversations
GROUP BY buyer, conversation
ORDER BY time_started
几句解释:
lag IS NULL
)或前一次呼叫超过45分钟的行。因此,这些是我称之为“对话”的最初调用。对话获取一个列和一个id,它只是查询中的行号,另一列用于跟踪对话“呼叫”中的呼叫数。答案 2 :(得分:1)
感谢Patrick关于原始版本的通知。 你在这里肯定需要WINDOW函数,但CTE在这里是可选的。
STICKY SERVICE