获取每天的活跃用户数
Get count of active users for each day
我有一个数据可以让用户了解用户何时订阅服务、在城市中以及何时到期。
如下
+------+------------+------------+
| City | Start_Date | End_Date |
+------+------------+------------+
| LA | 2019-06-01 | 2019-06-03 |
| LA | 2019-06-07 | 2019-06-10 |
| LA | 2019-06-09 | 2019-06-11 |
| LA | 2019-06-13 | 2019-06-14 |
| LO | 2019-06-01 | 2019-06-05 |
| LO | 2019-06-04 | 2019-06-05 |
| LO | 2019-06-07 | 2019-06-09 |
| LO | 2019-06-08 | 2019-06-09 |
+------+------------+------------+
我想知道每个城市在给定日期每天的活跃用户数
输出应该与
有点相似
+------+------------+-------+
| City | Day | Count |
+------+------------+-------+
| LA | 2019-06-01 | 1 |
| LA | 2019-06-02 | 1 |
| LA | 2019-06-03 | 1 |
| LA | 2019-06-04 | 0 |
| LA | 2019-06-05 | 0 |
| LA | 2019-06-06 | 0 |
| LA | 2019-06-07 | 1 |
| LA | 2019-06-08 | 1 |
| LA | 2019-06-09 | 2 |
| LA | 2019-06-10 | 2 |
| LA | 2019-06-11 | 1 |
| LA | 2019-06-12 | 0 |
| LA | 2019-06-13 | 1 |
| LA | 2019-06-14 | 1 |
| LA | 2019-06-15 | 0 |
+------+------------+-------+
我显示的输出仅适用于城市 LA
,我还希望 table.
中的每个城市都有类似的输出
我的输出描述
- 在
Day = 2019-06-01
的 City = LA
中,有 1 位用户订阅有效,Day = 2019-06-02
也是如此。
- 在
Day = 2019-06-09
的 City = LA
中,有 2 位用户订阅有效,依此类推。
任何帮助将不胜感激
这样应该可行:
select city, '2019-06-11', count(*)
from table1
where end_date >= '2019-06-11'
group by 1
你应该用变量替换日期并放入你需要的日期。
首先制作这个有用的计数Table查看
/****** Object: View [dbo].[cteTally] Script Date: 10/06/2019 11:02:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
然后你可以像这样生成你要查询的日期列表(下面这个查询只是演示,不是编码完成)
Declare @Start as date = '20170101';
Declare @End as date = '20190601';
SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End;
现在我们可以扩展它来计算日期范围匹配的记录
SELECT Y.City, DQ.aDate, Count(Y.City) as DayCountForCity FROM (SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End) DQ
LEFT JOIN YourTable Y ON DQ.adate BETWEEN Y.Start_Date AND Y.End_Date
GRoup By Y.City, DQ.adate
用你给定的测试试试这个 table
Declare @Start as date = '20170101';
Declare @End as date = '20450601';
SELECT * FROM (SELECT Y.City, DQ.aDate, Count(Y.City) as DayCountForCity FROM (SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End) DQ
LEFT JOIN Table1 Y ON DQ.adate BETWEEN Y.Start_Date AND Y.End_Date
GRoup By Y.City, DQ.adate) Q1 WHERE Q1.city is not null
order by city, adate
您需要一个日期范围。数字或计数 table 很方便。但是递归 CTE 也很有帮助。
然后使用 CROSS JOIN
分配行,使用 LEFT JOIN
引入您想要的值,然后使用 GROUP BY
获取计数:
with dates as (
select convert(date, '2019-06-01') as dte
union all
select dateadd(day, 1, dte) as dte
from dates
where dte < '2019-06-15'
)
select c.city, d.dte, count(t.city)
from (select distinct city from t) c cross join
dates d left join
t
on t.city = c.city and t.start_date <= d.dte and d.end_date >= t.dte
group by c.city, d.dte
order by c.city, d.dte;
Here 是一个 db<>fiddle -- 使用 SQL 服务器。
试试下面的查询。测试数据:
DECLARE @tbl TABLE (City varchar(5),Start_Date date,End_Date date);
INSERT INTO @tbl values
( 'LA','2019-06-01','2019-06-03' ),
( 'LA','2019-06-07','2019-06-10' ),
( 'LA','2019-06-09','2019-06-11' ),
( 'LA','2019-06-13','2019-06-14' ),
( 'LO','2019-06-01','2019-06-05' ),
( 'LO','2019-06-04','2019-06-05' ),
( 'LO','2019-06-07','2019-06-09' ),
( 'LO','2019-06-08','2019-06-09' );
使用 CTE 作为日历函数的实际查询:
DECLARE @start DATE, @end DATE;
SELECT @start = MIN(Start_Date), @end = MAX(End_Date) FROM @tbl;
;WITH cte AS (
SELECT @start dt
UNION ALL
SELECT DATEADD(day, 1, dt) FROM CTE
WHERE dt < @end
)
SELECT cte.dt, SUM(CASE WHEN t.City IS NULL THEN 0 ELSE 1 END) FROM cte
LEFT JOIN @tbl t
ON cte.dt BETWEEN t.Start_Date AND t.End_Date AND t.City = 'LA'
GROUP BY cte.dt
你也可以这样做
DECLARE @MN DATETIME = (SELECT MIN(Start_Date) FROM T),
@MX DATETIME = (SELECT MAX(End_Date) FROM T);
;WITH CTE AS
(
SELECT @MN D
UNION ALL
SELECT DATEADD(Day, 1, D)
FROM CTE
WHERE D <= @MX
)
SELECT TT.City,
CTE.D [Day],
(
SELECT COUNT(1)
FROM T T1
WHERE T1.City = TT.City
AND CTE.D BETWEEN T1.Start_Date AND T1.End_Date
) Cnt
FROM CTE CROSS JOIN (VALUES('LA')) TT(City);
Returns:
+------+---------------------+-----+
| City | Day | Cnt |
+------+---------------------+-----+
| LA | 01/06/2019 00:00:00 | 1 |
| LA | 02/06/2019 00:00:00 | 1 |
| LA | 03/06/2019 00:00:00 | 1 |
| LA | 04/06/2019 00:00:00 | 0 |
| LA | 05/06/2019 00:00:00 | 0 |
| LA | 06/06/2019 00:00:00 | 0 |
| LA | 07/06/2019 00:00:00 | 1 |
| LA | 08/06/2019 00:00:00 | 1 |
| LA | 09/06/2019 00:00:00 | 2 |
| LA | 10/06/2019 00:00:00 | 2 |
| LA | 11/06/2019 00:00:00 | 1 |
| LA | 12/06/2019 00:00:00 | 0 |
| LA | 13/06/2019 00:00:00 | 1 |
| LA | 14/06/2019 00:00:00 | 1 |
| LA | 15/06/2019 00:00:00 | 0 |
+------+---------------------+-----+
SELECT date,city,count(id) as total FROM table WHERE STR_TO_DATE("2019-06-01","%Y-%m-%d") = STR_TO_DATE("2019-06-01","%Y-%m-%d") GROUP BY city
我有一个数据可以让用户了解用户何时订阅服务、在城市中以及何时到期。
如下
+------+------------+------------+
| City | Start_Date | End_Date |
+------+------------+------------+
| LA | 2019-06-01 | 2019-06-03 |
| LA | 2019-06-07 | 2019-06-10 |
| LA | 2019-06-09 | 2019-06-11 |
| LA | 2019-06-13 | 2019-06-14 |
| LO | 2019-06-01 | 2019-06-05 |
| LO | 2019-06-04 | 2019-06-05 |
| LO | 2019-06-07 | 2019-06-09 |
| LO | 2019-06-08 | 2019-06-09 |
+------+------------+------------+
我想知道每个城市在给定日期每天的活跃用户数
输出应该与
有点相似+------+------------+-------+
| City | Day | Count |
+------+------------+-------+
| LA | 2019-06-01 | 1 |
| LA | 2019-06-02 | 1 |
| LA | 2019-06-03 | 1 |
| LA | 2019-06-04 | 0 |
| LA | 2019-06-05 | 0 |
| LA | 2019-06-06 | 0 |
| LA | 2019-06-07 | 1 |
| LA | 2019-06-08 | 1 |
| LA | 2019-06-09 | 2 |
| LA | 2019-06-10 | 2 |
| LA | 2019-06-11 | 1 |
| LA | 2019-06-12 | 0 |
| LA | 2019-06-13 | 1 |
| LA | 2019-06-14 | 1 |
| LA | 2019-06-15 | 0 |
+------+------------+-------+
我显示的输出仅适用于城市 LA
,我还希望 table.
我的输出描述
- 在
Day = 2019-06-01
的City = LA
中,有 1 位用户订阅有效,Day = 2019-06-02
也是如此。 - 在
Day = 2019-06-09
的City = LA
中,有 2 位用户订阅有效,依此类推。
任何帮助将不胜感激
这样应该可行:
select city, '2019-06-11', count(*)
from table1
where end_date >= '2019-06-11'
group by 1
你应该用变量替换日期并放入你需要的日期。
首先制作这个有用的计数Table查看
/****** Object: View [dbo].[cteTally] Script Date: 10/06/2019 11:02:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
然后你可以像这样生成你要查询的日期列表(下面这个查询只是演示,不是编码完成)
Declare @Start as date = '20170101';
Declare @End as date = '20190601';
SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End;
现在我们可以扩展它来计算日期范围匹配的记录
SELECT Y.City, DQ.aDate, Count(Y.City) as DayCountForCity FROM (SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End) DQ
LEFT JOIN YourTable Y ON DQ.adate BETWEEN Y.Start_Date AND Y.End_Date
GRoup By Y.City, DQ.adate
用你给定的测试试试这个 table
Declare @Start as date = '20170101';
Declare @End as date = '20450601';
SELECT * FROM (SELECT Y.City, DQ.aDate, Count(Y.City) as DayCountForCity FROM (SELECT dateadd(day, N-1,@Start) aDate from [dbo].[cteTally] WHERE dateadd(day, N-1,@Start) <= @End) DQ
LEFT JOIN Table1 Y ON DQ.adate BETWEEN Y.Start_Date AND Y.End_Date
GRoup By Y.City, DQ.adate) Q1 WHERE Q1.city is not null
order by city, adate
您需要一个日期范围。数字或计数 table 很方便。但是递归 CTE 也很有帮助。
然后使用 CROSS JOIN
分配行,使用 LEFT JOIN
引入您想要的值,然后使用 GROUP BY
获取计数:
with dates as (
select convert(date, '2019-06-01') as dte
union all
select dateadd(day, 1, dte) as dte
from dates
where dte < '2019-06-15'
)
select c.city, d.dte, count(t.city)
from (select distinct city from t) c cross join
dates d left join
t
on t.city = c.city and t.start_date <= d.dte and d.end_date >= t.dte
group by c.city, d.dte
order by c.city, d.dte;
Here 是一个 db<>fiddle -- 使用 SQL 服务器。
试试下面的查询。测试数据:
DECLARE @tbl TABLE (City varchar(5),Start_Date date,End_Date date);
INSERT INTO @tbl values
( 'LA','2019-06-01','2019-06-03' ),
( 'LA','2019-06-07','2019-06-10' ),
( 'LA','2019-06-09','2019-06-11' ),
( 'LA','2019-06-13','2019-06-14' ),
( 'LO','2019-06-01','2019-06-05' ),
( 'LO','2019-06-04','2019-06-05' ),
( 'LO','2019-06-07','2019-06-09' ),
( 'LO','2019-06-08','2019-06-09' );
使用 CTE 作为日历函数的实际查询:
DECLARE @start DATE, @end DATE;
SELECT @start = MIN(Start_Date), @end = MAX(End_Date) FROM @tbl;
;WITH cte AS (
SELECT @start dt
UNION ALL
SELECT DATEADD(day, 1, dt) FROM CTE
WHERE dt < @end
)
SELECT cte.dt, SUM(CASE WHEN t.City IS NULL THEN 0 ELSE 1 END) FROM cte
LEFT JOIN @tbl t
ON cte.dt BETWEEN t.Start_Date AND t.End_Date AND t.City = 'LA'
GROUP BY cte.dt
你也可以这样做
DECLARE @MN DATETIME = (SELECT MIN(Start_Date) FROM T),
@MX DATETIME = (SELECT MAX(End_Date) FROM T);
;WITH CTE AS
(
SELECT @MN D
UNION ALL
SELECT DATEADD(Day, 1, D)
FROM CTE
WHERE D <= @MX
)
SELECT TT.City,
CTE.D [Day],
(
SELECT COUNT(1)
FROM T T1
WHERE T1.City = TT.City
AND CTE.D BETWEEN T1.Start_Date AND T1.End_Date
) Cnt
FROM CTE CROSS JOIN (VALUES('LA')) TT(City);
Returns:
+------+---------------------+-----+
| City | Day | Cnt |
+------+---------------------+-----+
| LA | 01/06/2019 00:00:00 | 1 |
| LA | 02/06/2019 00:00:00 | 1 |
| LA | 03/06/2019 00:00:00 | 1 |
| LA | 04/06/2019 00:00:00 | 0 |
| LA | 05/06/2019 00:00:00 | 0 |
| LA | 06/06/2019 00:00:00 | 0 |
| LA | 07/06/2019 00:00:00 | 1 |
| LA | 08/06/2019 00:00:00 | 1 |
| LA | 09/06/2019 00:00:00 | 2 |
| LA | 10/06/2019 00:00:00 | 2 |
| LA | 11/06/2019 00:00:00 | 1 |
| LA | 12/06/2019 00:00:00 | 0 |
| LA | 13/06/2019 00:00:00 | 1 |
| LA | 14/06/2019 00:00:00 | 1 |
| LA | 15/06/2019 00:00:00 | 0 |
+------+---------------------+-----+
SELECT date,city,count(id) as total FROM table WHERE STR_TO_DATE("2019-06-01","%Y-%m-%d") = STR_TO_DATE("2019-06-01","%Y-%m-%d") GROUP BY city