我有一个联系人列表,以及三个包含不同信息的表格,其中包含有关联系人的日期相关数据。
我想做的是显示每个表的每月计数:
ID Date Hist Trck Evt
1 2016-01-01 0 0 0
1 2016-02-01 1 0 1
1 2016-03-01 2 0 1
1 2016-04-01 0 5 1
我通过对PersonId和Date进行分组来单独获得每种类型的结果:
SELECT PersonId AS CID,
HistoryDate,
COUNT(id) Records
FROM @History
GROUP BY PersonId,
HistoryDate
这会得到3个数据表的总数,但不按人员ID分组:
SELECT DateMonth, pvt.[EH], pvt.[ET], pvt.[EV]
FROM
(
SELECT Id AS CID, HistoryDate AS DateMonth, 'EH' AS RecordType, COUNT(id) Records FROM @History GROUP BY Id, HistoryDate
UNION ALL
SELECT Id AS CID, TrackingDate AS DateMonth, 'ET' AS RecordType, COUNT(id) Records FROM @Tracking GROUP BY Id, TrackingDate
UNION ALL
SELECT Id AS CID, EventDate AS DateMonth, 'EV' AS RecordType, COUNT(id) Records FROM @Events GROUP BY Id, EventDate
) as x
PIVOT( COUNT(CID) FOR RecordType IN ( [EH], [ET], [EV] ) ) as pvt
DateMonth EH ET EV
----------------------- ----------- ----------- -----------
2016-02-01 00:00:00.000 1 1 1
2016-03-01 00:00:00.000 2 0 1
2016-04-01 00:00:00.000 0 5 1
2016-05-01 00:00:00.000 1 2 0
2016-06-01 00:00:00.000 2 2 0
2016-07-01 00:00:00.000 2 0 0
2016-08-01 00:00:00.000 2 0 0
我似乎无法向枢轴添加第二列,因此它有Id
,DateMonth
,然后是三个透视字段。
我正在努力将这些内容与联系人数据合并到一个记录集中。
我实际得到的是每个联系人和日期的大量记录,而不是一个。
我怀疑这是显而易见的事情,但是随着时间的推移,这些要求已经发生了变化(实际上这些表格很复杂而且非常庞大)所以我可能只是让我的思绪陷入了死胡同。
这是一些示例架构。 (您也可以运行它here)
DECLARE @Contacts TABLE (
Id int not null,
Email nvarchar(50)
);
DECLARE @History TABLE (
Id int not null,
PersonId int,
HistoryDate datetime
);
DECLARE @Tracking TABLE (
Id int not null,
PersonId int,
TrackingDate datetime
);
DECLARE @Events TABLE (
Id int not null,
PersonId int,
EventDate datetime
);
以下是一位联系人的一些示例数据:
INSERT INTO @Contacts VALUES (1, 'someone@gmail.com');
INSERT INTO @History VALUES (1, 1, '2016-02-01');
INSERT INTO @History VALUES (2, 1, '2016-03-01');
INSERT INTO @History VALUES (3, 1, '2016-03-01');
INSERT INTO @History VALUES (4, 1, '2016-05-01');
INSERT INTO @History VALUES (5, 1, '2016-06-01');
INSERT INTO @History VALUES (6, 1, '2016-06-01');
INSERT INTO @History VALUES (7, 1, '2016-07-01');
INSERT INTO @History VALUES (8, 1, '2016-07-01');
INSERT INTO @History VALUES (9, 1, '2016-08-01');
INSERT INTO @History VALUES (10,1, '2016-08-01');
INSERT INTO @Tracking VALUES (1, 1, '2016-02-01');
INSERT INTO @Tracking VALUES (2, 1, '2016-04-01');
INSERT INTO @Tracking VALUES (3, 1, '2016-04-01');
INSERT INTO @Tracking VALUES (4, 1, '2016-04-01');
INSERT INTO @Tracking VALUES (5, 1, '2016-04-01');
INSERT INTO @Tracking VALUES (6, 1, '2016-04-01');
INSERT INTO @Tracking VALUES (7, 1, '2016-05-01');
INSERT INTO @Tracking VALUES (8, 1, '2016-05-01');
INSERT INTO @Tracking VALUES (9, 1, '2016-06-01');
INSERT INTO @Tracking VALUES (19, 1, '2016-06-01');
INSERT INTO @Events VALUES (1, 1, '2016-02-01');
INSERT INTO @Events VALUES (2, 1, '2016-03-01');
INSERT INTO @Events VALUES (3, 1, '2016-04-01');
答案 0 :(得分:1)
您的查询修补程序
CID
)中使用了COUNT(CID)
,因此不被用作PIVOT聚合列之一,您无法选择它。 PersonId
与Id
COUNT(CID)
替换为SUM(Recrods)
并将CID
添加到SELECT子句中。PersonId
替换为Id
coalesce (...,0)
SELECT CID,DateMonth, pvt.[EH], pvt.[ET], pvt.[EV]
FROM
(
SELECT PersonId AS CID, HistoryDate AS DateMonth, 'EH' AS RecordType, COUNT(id) Records FROM @History GROUP BY PersonId, HistoryDate
UNION ALL
SELECT PersonId AS CID, TrackingDate AS DateMonth, 'ET' AS RecordType, COUNT(id) Records FROM @Tracking GROUP BY PersonId, TrackingDate
UNION ALL
SELECT PersonId AS CID, EventDate AS DateMonth, 'EV' AS RecordType, COUNT(id) Records FROM @Events GROUP BY PersonId, EventDate
) as x
PIVOT( SUM(Records) FOR RecordType IN ( [EH], [ET], [EV] ) ) as pvt
更清洁的解决方案
select cid,datemonth,h,t,v
from ( select PersonId, historydate ,'h' from @history
union all select PersonId, trackingdate ,'t' from @tracking
union all select PersonId, eventdate ,'v' from @events
) as t (cid,datemonth,recordtype)
pivot (count(recordtype) for recordtype in (h,t,v)) as p
+-----+-------------------------+----+----+----+
| cid | datemonth | h | t | v |
+-----+-------------------------+----+----+----+
| 1 | 2016-02-01 00:00:00.000 | 1 | 1 | 1 |
+-----+-------------------------+----+----+----+
| 1 | 2016-03-01 00:00:00.000 | 2 | 0 | 1 |
+-----+-------------------------+----+----+----+
| 1 | 2016-04-01 00:00:00.000 | 0 | 5 | 1 |
+-----+-------------------------+----+----+----+
| 1 | 2016-05-01 00:00:00.000 | 1 | 2 | 0 |
+-----+-------------------------+----+----+----+
| 1 | 2016-06-01 00:00:00.000 | 2 | 2 | 0 |
+-----+-------------------------+----+----+----+
| 1 | 2016-07-01 00:00:00.000 | 2 | 0 | 0 |
+-----+-------------------------+----+----+----+
| 1 | 2016-08-01 00:00:00.000 | 2 | 0 | 0 |
+-----+-------------------------+----+----+----+
答案 1 :(得分:0)
在postsgresql中你可以使用
GROUP BY date_trunc('month', date_column)
答案 2 :(得分:0)
可能你可以做得更好但是有效。
WITH eventss as (
SELECT COUNT(ID) as cnt, PERSONID, YEAR(eventdate) as y, MONTH(eventdate) as m
FROM @Events
GROUP BY PERSONID, YEAR(eventdate), MONTH(eventdate)
),
tracking as (
SELECT COUNT(ID) as cnt, PERSONID, YEAR(trackingdate) as y, MONTH(trackingdate) as m
FROM @Tracking
GROUP BY PERSONID, YEAR(trackingdate), MONTH(trackingdate)
),
history as (
SELECT COUNT(ID) as cnt, PERSONID, YEAR(historydate) as y, MONTH(historydate) as m
FROM @History
GROUP BY PERSONID, YEAR(historydate), MONTH(historydate)
),
ttime as ( SELECT YEAR(historydate) as y,MONTH(historydate) as m FROM @History UNION
SELECT YEAR(trackingdate) as y,MONTH(trackingdate) as m FROM @Tracking UNION
SELECT YEAR(eventdate) as y,MONTH(eventdate) as m FROM @Events
)
SELECT c.id, DATEFROMPARTS(tt.y,tt.m,1) as date, ISNULL(h.cnt,0) as Hist, ISNULL(tr.cnt,0) as Trck, ISNULL(e.cnt,0) as Evt
FROM @Contacts AS c
CROSS JOIN ttime AS tt
LEFT JOIN eventss AS e ON c.Id=e.PERSONID AND tt.m=e.m AND tt.y=e.y
LEFT JOIN tracking AS tr ON c.Id=tr.PERSONID AND tt.m=tr.m AND tt.y=tr.y
LEFT JOIN history AS h ON c.Id=h.PERSONID AND tt.m=h.m AND tt.y=h.y