每年每年的唯一身份用户数据透视

时间:2019-04-25 13:40:06

标签: sql sql-server pivot

我正在学习PIVOT函数,我想在数据库DDOT中尝试使用它,我有用户在X年Y年以YYYYMM格式进行的事件(行)。

id_ev iddate id_user ...
------------------------
1     201901 321
2     201902 654
3     201903 987
4     201901 321
5     201903 987

我将查询基于MS Documentation,但没有收到错误,但无法用那些唯一事件(用户)的总和来填充它。简而言之,我想知道一年(y轴)中每个月(x轴)检查了多少用户(唯一)。但是,结果为NULL

YYYY    jan     feb     mar
----------------------------
2019    NULL    NULL    NULL

我希望有一张我之前提到的完整表格。

YYYY    jan     feb     mar
----------------------------
2019    2       1       1

在我尝试使用不同聚合函数的代码中,但是此块最接近SQL的结果。

CREATE TABLE ddot
(
 id_ev   int NOT NULL ,
 iddate  int NOT NULL ,
 id_user int NOT NULL 

);

INSERT INTO DDOT
(
 [id_ev], [iddate], [id_user]
)
VALUES
(
 1, 201901, 321
),
(
 2, 201902, 654
),
(
 3, 201903, 987
),
(
 4, 201901, 321
),
(
 5, 201903, 987
)
GO

SELECT *
FROM (
        SELECT COUNT(DISTINCT id_user) [TOT],
                DATENAME(YEAR, CAST(iddate+'01' AS DATETIME)) [YYYY], --concat iddate 01 to get full date
                DATENAME(MONTH, CAST(iddate+'01' AS DATETIME)) [MMM]

        FROM DDOT
        GROUP BY DATENAME(YEAR, CAST(iddate+'01' AS DATETIME)),
                DATENAME(MONTH, CAST(iddate+'01' AS DATETIME))
) AS DOT_COUNT
PIVOT(
        SUM([TOT])
        FOR MMM IN (jan, feb, mar)
) AS PVT

1 个答案:

答案 0 :(得分:3)

理想情况下,您应该在iddate列中使用实际日期,而不是字符串(数字?)。我们可以使用字符串函数来解决此问题:

SELECT
    CONVERT(varchar(4), LEFT(iddate, 4)) AS YYYY,
    COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '01' THEN 1 END) AS jan,
    COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '02' THEN 1 END) AS feb,
    COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '03' THEN 1 END) AS mar,
    ...
FROM DDOT
GROUP BY
    CONVERT(varchar(4), LEFT(iddate, 4));

请注意,如果iddate列已经是文本,那么我们可以删除上面对CONVERT的所有丑陋调用:

SELECT
    LEFT(iddate, 4) AS YYYY,
    COUNT(CASE WHEN RIGHT(iddate, 2) = '01' THEN 1 END) AS jan,
    COUNT(CASE WHEN RIGHT(iddate, 2) = '02' THEN 1 END) AS feb,
    COUNT(CASE WHEN RIGHT(iddate, 2) = '03' THEN 1 END) AS mar,
    ...
FROM DDOT
GROUP BY
    LEFT(iddate, 4);