我正在尝试使用以下查询计算两个日期之间的差值
with cte (clientid, calls)
as
(
select clientid, max(isnull(cast(calls as int),0)) as calls from STATS
where clientid != 0
group by CLIENTID),
cteb (minCal, calls, clientid)
as
(
select calendar as minCal, (cast(calls as int)) as calls, CLIENTID from STATS
)
select min(CONVERT(datetime, convert(varchar(10), minCalendar))) as dayHighCall, cte.clientid, max(cte.calls) as highestCall from cte
join cteb
on cteb.clientid = cte.clientid
where cteb.tot = cte.totalcalls
group by cte.clientid)
它返回此输出
dayHighCall clientid highestCall
2017-11-27 00:00:00.000 2200 2
2017-11-17 00:00:00.000 2500 65
我希望它返回另一个日期,因此我将其写为上述查询的扩展-
cted as
(
select min(CONVERT(datetime, convert(varchar(10), CALENDAR))) as mincal from STATS
group by CLIENTID
)
现在,我希望通过以下查询获得结果-
select cte.clientid,
DATEDIFF(day,
ctec.dayHighCall,
mincal)
as datedifference
from cte, ctec, cted
group by cte.clientid
这会在ctec.dayHighCall
和mincal
上引发错误,因为它们既不是集合也不是子查询的一部分。如何修改此查询,以便得到clientid
,datediff
和calls
的结果。
答案 0 :(得分:1)
我猜您有一个STATS
表,每个客户(CLIENTID
)和日期(calendar
)最多有一行。
我不得不用更清晰的名称和注释(修正不匹配的名称,从而使查询在此过程中无效)重新编写代码,以了解您要执行的操作:
with daily_stats as (
select clientid
, isnull(cast(calls as int),0) as num_calls
-- whatever the format of "calendar" is, you made sure this converted it to datetime properly
, convert(datetime, convert(varchar(10), calendar)) as date
from STATS
where clientid != 0
)
, max_calls_for_client as ( -- this was "cte"
select clientid, max(calls) as max_daily_calls from daily_stats group by clientid
)
, date_with_highest_calls as ( -- this was "ctec", presumably - the query for which you provided an example result
select a.clientid
, min(b.date) as dayHighCall -- the first day with the highest number of calls
, max(a.max_daily_calls) as max_daily_calls
from max_calls_for_client a
join daily_stats b
on a.clientid = b.clientid
and a.max_daily_calls = b.num_calls -- get the date(s) with the maximum number of calls
group by a.clientid
)
, first_call_date as ( -- "cted"
select clientid, min(date) as min_call_date from daily_stats group by clientid
)
select max_calls_for_client.clientid
, DATEDIFF(day,
date_with_highest_calls.dayHighCall,
first_call_date.min_call_Date) as datedifference
from max_calls_for_client
, date_with_highest_calls
, first_call_date
group by max_calls_for_client.clientid
如果我猜对了,那么通过加入客户机ID可以很容易地解决您的最后一点问题:您有三个“表”,每个表都按客户机ID分组,需要将它们组合在一起,所以这应该起作用:>
from max_calls_for_client a
join date_with_highest_calls b on a.clientid = b.clientid
join first_call_date c on a.clientid = c.clientid
还请注意,您可以分两个步骤执行此操作,而不是四个步骤:
first_call_date
和max_calls_for_client
合并为一个(我们称其为client_stats
),因为两者都是clientid
上的简单聚合。然后,您可以在同一查询中计算找到呼叫次数最多的日期的天数:
select c.clientid
, min(d.date) as dayHighCall -- the first day with the highest number of calls
-- aggregations are no-op here, as `client_stats` has a single value for each clientid
, max(c.min_call_date) as max_daily_calls
, max(c.max_daily_calls) as max_daily_calls
, DATEDIFF(day,
min(d.date), -- the first day with the highest number of calls
max(c.min_call_date)
) as datedifference
from client_stats c
join daily_stats d
on c.clientid = d.clientid
and c.max_daily_calls = d.num_calls
group by c.clientid
答案 1 :(得分:1)
如果您使用的是SQL Server 2012或更高版本,则不需要CTE,则可以使用适当的分区通过FIRST_VALUE函数解决此问题
SELECT DISTINCT
ClientID,
FIRST_VALUE(Calendar) OVER (PARTITION BY ClientID ORDER BY Calls DESC) AS dayHighCall,
MAX(Calls) OVER (PARTITION BY ClientID) AS highestCall,
DATEDIFF(DAY, MIN(Calendar) OVER (), FIRST_VALUE(Calendar) OVER (PARTITION BY ClientID ORDER BY Calls DESC)) AS datedifference
FROM STATS
ORDER BY ClientID
如果您使用的是旧版SQL Server,则可以使用CTE和CROSS APPLY
;WITH CTE AS (
SELECT DISTINCT ClientID, MAX(Calls) OVER (Partition BY ClientID) AS Calls, MIN(Calendar) OVER () AS minCalendar
FROM STATS
),
SELECT
ClientID,
dayHighCall.Calendar AS dayHighCall,
Calls AS highestCall,
DATEDIFF(day, minCalendar, dayHighCall.Calendar) datedifference
FROM CTE
CROSS APPLY (
SELECT TOP 1 Calendar FROM STATS S WHERE S.ClientID = CTE.ClientID AND S.Calls = CTE.Calls
) dayHighCall
ORDER BY ClientID
PS。我假设您的minCal用于整个表,如果您还需要ClientID,则可以将Partition By添加到两个Over()子句中的任何一个