我有一个表格,用于跟踪从我服务器上的应用程序发送的电子邮件。我想写一个查询,显示每个应用程序在特定时间段内发送了多少封电子邮件。这是表格:
----------------------------------------------------------
| emailID | SentDT | ApplicationName |
----------------------------------------------------------
| 1 | 2011-08-04 14:43:31.080 | Term Form |
----------------------------------------------------------
| 2 | 2011-08-04 13:59:46.062 | Term Form |
----------------------------------------------------------
| 3 | 2011-08-03 10:38:15.015 | Request Form |
----------------------------------------------------------
| 4 | 2011-08-03 05:52:29.005 | Term Form |
----------------------------------------------------------
| 5 | 2011-08-01 19:58:31.094 | Recruiting Form |
----------------------------------------------------------
我希望看到今天,过去24小时,过去7天,本月,上个月,所有时间发送的电子邮件数量。
我知道如何自己完成这些查询,但我不知道如何在一次数据库中做到这一点。
例如:
--------------------------------------------------------------
| ApplicationName | Today | Last24 | Last7days | ThisMonth |
--------------------------------------------------------------
| Term Form | 2 | 5 | 10 | 19 |
--------------------------------------------------------------
| Request Form | 9 | 18 | 36 | 75 |
--------------------------------------------------------------
| Recruiting Form | 15 | 35 | 100 | 250 |
--------------------------------------------------------------
我尝试对每个子集使用嵌套选择,但我不能在嵌套选择中使用group by
。我的查询不会产生结果:
select COUNT(emailID), ApplicationName, (select COUNT(emailID) from emaillog where SentDT > '08/02/2011') as TwoDaysAgo
from emaillog
group by ApplicationName
order by ApplicationName
答案 0 :(得分:3)
我认为事先做所有日期计算要容易得多,然后你可以用逻辑名称引用局部变量,而不是在查询逻辑中嵌入所有的约会/案例等计算。
在这里做了几个假设。 (1)未来电子邮件日志中没有数据(2)表示今天和过去6天之前的“过去7天”。我还包括一个总计 - 虽然它没有列在你想要的输出中,但似乎你试图用子查询之外的COUNT()
得到它。
DECLARE @now SMALLDATETIME = SYSDATETIME();
DECLARE @today DATE = @now,
@24hrsago SMALLDATETIME = DATEADD(DAY, -1, @now);
DECLARE @7daysago DATE = DATEADD(DAY, -6, @today),
@ThisMonth DATE = DATEADD(DAY, 1-DATEPART(DAY, @today), @today);
--SELECT @now, @today, @24hrsago, @7daysago, @ThisMonth;
WITH d AS
(
SELECT ApplicationName, c = COUNT(*)
FROM EmailLog
GROUP BY ApplicationName
),
g AS
(
SELECT
ApplicationName,
[Today] = SUM(CASE WHEN SentDt >= @today THEN 1 ELSE 0 END),
[Last24] = SUM(CASE WHEN SentDt >= @24hrsago THEN 1 ELSE 0 END),
[Last7Days] = SUM(CASE WHEN SentDt >= @7daysago THEN 1 ELSE 0 END),
[ThisMonth] = SUM(CASE WHEN SentDt >= @ThisMonth THEN 1 ELSE 0 END)
FROM EmailLog
GROUP BY ApplicationName
)
SELECT d.ApplicationName,
Total = d.c,
[Today] = COALESCE(g.[Today], 0),
[Last24] = COALESCE(g.[Last24], 0),
[Last7days] = COALESCE(g.Last7days, 0),
[ThisMonth] = COALESCE(g.ThisMonth, 0)
FROM d LEFT OUTER JOIN g
ON d.ApplicationName = g.ApplicationName;
编辑
如果我的假设是错误的,并且您不需要应用程序名称的总计数,则查询会变得更加简单:
DECLARE @now SMALLDATETIME = SYSDATETIME();
DECLARE @today DATE = @now,
@24hrsago SMALLDATETIME = DATEADD(DAY, -1, @now);
DECLARE @7daysago DATE = DATEADD(DAY, -6, @today),
@ThisMonth DATE = DATEADD(DAY, 1-DATEPART(DAY, @today), @today);
SELECT ApplicationName,
[Today] = SUM(CASE WHEN SentDt >= @today THEN 1 ELSE 0 END),
[Last24] = SUM(CASE WHEN SentDt >= @24hrsago THEN 1 ELSE 0 END),
[Last7Days] = SUM(CASE WHEN SentDt >= @7daysago THEN 1 ELSE 0 END),
[ThisMonth] = SUM(CASE WHEN SentDt >= @ThisMonth THEN 1 ELSE 0 END)
FROM EmailLog
GROUP BY ApplicationName;
当然订购可选。
答案 1 :(得分:2)
尝试:
Select ApplicationName, COunt(*) numEmails
From table
where SentDT Between @startDateTime and @EndDateTime
Group By ApplicationName
注意:startDateTime和EndDateTime是要处理的记录的限制。
如果你还想在指定的日期范围内建立存储桶,你只需要通过表达式在另一个组中定义那些日期时间范围存储桶(并在select子句中输出相同的表达式...作为一个例子,比如日期时间范围是历月...
Select DateAdd(month, DateDiff(month, 0, SentDT), 0) CalMonth,
ApplicationName, Count(*) numEmails
From table
where SentDT Between @startDateTime and @EndDateTime
Group By DateAdd(month, DateDiff(month, 0, SentDT), 0),
ApplicationName
答案 2 :(得分:1)
这样的事情可以解决问题
select
ApplicationName,
sum(case when daterange = 0 then cnt else 0 end) as Today,
sum(case when daterange = 1 then cnt else 0 end) as yesterday,
sum(case when daterange <=2 then cnt else 0 end) as Week,
sum(case when daterange <=3 then cnt else 0 end) as month,
sum(cnt) as AllTime
from
(select
ApplicationName,
case
when days = 0 then '0'
when days = 1 then '1'
when days <= 7 then '2'
when days <= 30 then '3'
else 4
end as
DateRange,
Count(emailid) cnt
from
(select ApplicationName, EmailID, datediff(dd, SentDT, getdate()) as Days
from
dbo.[YourTableGoesHere]
) as foo
Group by
ApplicationName,
case when days < 1 then '0'
when days = 1 then '1'
when days <= 7 then '2'
when days <= 30 then '3'
else 4
end) as bar
group by
ApplicationName