我有下表(称为row_id session_id date_end user_id item_id
---------------------------------------------------
3962 5958255 2017-11-07 3249480 1
4553 5959689 2017-11-07 3249484 1
4554 5959689 2017-11-07 3249484 1
8775 5968439 2017-11-08 3249492 4
6706 5965190 2017-11-08 3249492 2
6779 5965280 2017-11-08 3249492 3
6778 5965280 2017-11-08 3249492 3
8774 5968439 2017-11-08 3249492 4
6685 5965159 2017-11-08 3249502 1
5314 5962257 2017-11-07 3249504 1
5315 5962257 2017-11-07 3249504 1
13564 5982665 2017-11-09 3249510 1
13565 5982665 2017-11-09 3249510 1
238 5941818 2017-11-06 3249540 1
8078 5967039 2017-11-08 3249540 3
13981 5984747 2017-11-09 3249540 4
127080 6267047 2017-11-30 3249540 10
):
item_id
查询此数据库时,我需要3个新列:
item_id
作为当前行user_id 3249492
的商品计数但是,我需要在30天内完成所有这些计数。例如,row_id session_id date_end user_id item_id total same diff
8775 5968439 2017-11-08 3249492 4 5 1 3
6706 5965190 2017-11-08 3249492 2 4 0 3
6779 5965280 2017-11-08 3249492 3 3 1 1
6778 5965280 2017-11-08 3249492 3 2 0 1
8774 5968439 2017-11-08 3249492 4 1 0 0
的行应为:
SELECT row_id, session_id, date_end, user_id, item_id,
COUNT(item_id) OVER (PARTITION BY user_id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as total,
COUNT(item_id) OVER (PARTITION BY user_id, item_id ORDER BY item_id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as same
FROM table1
我有以下内容:
total
这会产生same
和diff
的正确值,但不会考虑30天的窗口。另外,我不知道从哪个@Component({
selector: "protocol-details",
providers: [PatientsService],
template: `
<div *ngIf="data == null ;then content else table_content"></div>
<ng-template #content>
No Accruals
</ng-template>
<ng-template #table_content>
<div class="container">
<div class="center">
<h3 style="color:#215081;"> Protocol Accrual for {{mdg}} for Protocol No. {{protocolNumber}}</h3>
</div>
<br>
<div class="form-group">
<div style="position:relative">
<div class="input-group" daterangepicker (selected)="selectedDate($event, mainInput)"
(cancelDaterangepicker)="calendarEventsHandler($event)"
(applyDaterangepicker)="calendarEventsHandler($event)"
(hideDaterangepicker)="calendarEventsHandler($event)"
(showDaterangepicker)="calendarEventsHandler($event)"
>
<span class="form-control uneditable-input" name="daterange" >
{{ mainInput.start | date:'M/dd/y' }} - {{ mainInput.end| date:'M/dd/y' }}
</span>
<span class="input-group-btn">
<a type="button" class="btn btn-default"><span class="glyphicon glyphicon-calendar"></span></a>
</span>
</div>
</div>
</div>
</ng-template>
列开始。
SQL小提琴:http://sqlfiddle.com/#!17/ac833/2
这个PostgreSQL 9.6
非常感谢任何帮助。
答案 0 :(得分:0)
我们可以使用自联接来获取30天的运行计数,而不是使用窗口函数。
WITH thirty_days_window AS (
SELECT table1.row_id, table1.item_id, "window".item_id AS other_item_id
FROM table1 join table1 AS "window" ON "window".user_id = table1.user_id AND
"window".date_end BETWEEN table1.date_end - interval '30 days' AND table1.date_end AND
"window".row_id <= table1.row_id
),
counts AS (
SELECT row_id,
COUNT(*) AS total,
COUNT(CASE WHEN item_id = other_item_id THEN 1 END) - 1 AS same,
COUNT(CASE WHEN item_id != other_item_id THEN 1 END) AS diff
FROM thirty_days_window GROUP BY row_id)
SELECT table1.row_id, session_id, date_end, user_id, table1.item_id,
total, same, diff
FROM table1 JOIN counts ON counts.row_id = table1.row_id
ORDER BY row_id;
第一部分thirty_days_window
通过在30天的时间内将每一行与所有具有相同user_id
的行连接在一起来创建窗口。我们还假设我们只希望row_id
比当前值低的行。
接下来,我们对行进行计数。 same
仅计算item_id
与连接行的item_id
相同的行(减去1以删除原始行),diff
的作用恰好相反,得到item_id
与加入的行不同的所有行。
最后,我们重新加入原始表以添加session_id
user_id
和date_end
。
使用小提琴中的数据得出的最终结果:
row_id | session_id | date_end | user_id | item_id | total | same | diff
--------+------------+------------+---------+---------+-------+------+------
6706 | 5965190 | 2017-11-08 | 3249492 | 151 | 1 | 0 | 0
6778 | 5965280 | 2017-11-08 | 3249492 | 151 | 2 | 1 | 0
6779 | 5965280 | 2017-11-08 | 3249492 | 158 | 3 | 0 | 2
8774 | 5968439 | 2017-11-08 | 3249492 | 151 | 4 | 2 | 1
8775 | 5968439 | 2017-11-08 | 3249492 | 158 | 5 | 1 | 3
47046 | 6063745 | 2017-11-15 | 3263305 | 157 | 1 | 0 | 0
47047 | 6063745 | 2017-11-15 | 3263305 | 158 | 2 | 0 | 1
59887 | 6094293 | 2017-11-16 | 3263305 | 157 | 3 | 1 | 1
59888 | 6094294 | 2017-11-16 | 3263305 | 157 | 4 | 2 | 1
60343 | 6095456 | 2017-11-16 | 3263305 | 157 | 5 | 3 | 1
60344 | 6095457 | 2017-11-16 | 3263305 | 157 | 6 | 4 | 1
69112 | 6116357 | 2017-11-17 | 3263305 | 157 | 7 | 5 | 1
71085 | 6119700 | 2017-11-18 | 3263305 | 157 | 8 | 6 | 1
71508 | 6120421 | 2017-11-18 | 3250078 | 157 | 1 | 0 | 0
71509 | 6120421 | 2017-11-18 | 3250078 | 152 | 2 | 0 | 1
71510 | 6120421 | 2017-11-18 | 3250078 | 156 | 3 | 0 | 2
71511 | 6120421 | 2017-11-18 | 3250078 | 154 | 4 | 0 | 3
71512 | 6120421 | 2017-11-18 | 3250078 | 151 | 5 | 0 | 4
71513 | 6120421 | 2017-11-18 | 3250078 | 158 | 6 | 0 | 5
72242 | 6121399 | 2017-11-18 | 3263305 | 157 | 9 | 7 | 1
75696 | 6126280 | 2017-11-19 | 3263305 | 157 | 10 | 8 | 1
76082 | 6126777 | 2017-11-19 | 3263305 | 157 | 11 | 9 | 1
77546 | 6129039 | 2017-11-19 | 3263305 | 157 | 12 | 10 | 1
83754 | 6143858 | 2017-11-20 | 3263305 | 157 | 13 | 11 | 1
91331 | 6167552 | 2017-11-22 | 3263305 | 157 | 14 | 12 | 1
92431 | 6171560 | 2017-11-22 | 3263305 | 157 | 15 | 13 | 1
95073 | 6177870 | 2017-11-23 | 3263305 | 157 | 16 | 14 | 1
95302 | 6178780 | 2017-11-23 | 3263305 | 157 | 17 | 15 | 1
287471 | 7164221 | 2018-02-10 | 4516965 | 154 | 1 | 0 | 0
288750 | 7170955 | 2018-02-11 | 4516965 | 158 | 2 | 0 | 1
288751 | 7170955 | 2018-02-11 | 4516965 | 151 | 3 | 0 | 2
(31 rows)
稍作考虑后,可以一次选择查询:
SELECT table1.row_id, MIN(table1.session_id),
MIN(table1.date_end), MIN(table1.user_id), MIN(table1.item_id),
COUNT(*) as total,
COUNT(CASE WHEN table1.item_id = windw.item_id THEN 1 END) - 1 AS same,
COUNT(CASE WHEN table1.item_id != windw.item_id THEN 1 END)
FROM table1 JOIN table1 AS windw ON windw.user_id = table1.user_id AND
windw.date_end BETWEEN table1.date_end - INTERVAL '30 days' AND table1.date_end AND
windw.row_id <= table1.row_id
GROUP BY table1.row_id ORDER BY table1.row_id;