Sql 每月、每年透视唯一用户

Sql 每月、每年透视唯一用户,sql,sql-server,pivot,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 我的查询是基于的,我没有得到错误,但我无法用这些唯一事件(用户)的总和来填充它。简单地说,我想知道一年

我正在学习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
我的查询是基于的,我没有得到错误,但我无法用这些唯一事件(用户)的总和来填充它。简单地说,我想知道一年中每月(x轴)有多少用户(唯一)检查(y轴)。然而,我得到的结果是空的

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

理想情况下,您应该在
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);

201902
不是日期(时间),作为日期时间,它是
2452-10-15
。这些日期都没有“秋天在1月、2月或3月,这就是为什么它不能像你预期的那样工作。使用正确的日期,你会得到正确的结果。:)问题的关键是将日期存储为整数。尝试只运行内部查询。十月份你只能坐一排。改为使用日期数据类型,这样会容易得多。更正,您要转换为日期的值是一个类似于
201904
201903+'01'=201903+1=201904
)的值,实际上是
2452-10-17 00:00:00.000
。如果您更正了数据类型,由于
不同,您仍然无法实际获得所需的结果,如果您将其删除,你也没有得到正确的结果。所以这里有些不对劲:@Larnu你是对的,我把它切换到了nvarchar,添加了
'01'
将日期正确地转换为我计算机的日期格式,但我仍然得到了空结果。谢谢你的建议!我已经把它换成了NVARCHAR。我知道我可以手动完成透视,但我的DW包含10年的数据,并且每个月都执行每一行。O.F.考虑使用传统的PIOVT,通常它可以胜过SQLServer的<代码> PIVOT < /Cord>查询。