我们正在使用MS SQL SERVER 2012。
我们正在记录每次用户拨打电话时,通过在用户拨打的每个电话的表格中添加日期时间和用户ID。
现在,我需要计算自创建以来用户的最高月度,每周,每日记录。
意思是,我需要计算自创建以来任何用户在给定月份内的最高月计数。所以记录每月计数,以及它的名称。
我不确定如何最好地去做。这就是我现在所创造的,我想知道是否有更好或更有效的方法来做到这一点。
以下是带样本的更新版本。 (我应用了日期更改,希望这有帮助)
这是月度记录:
DECLARE @id int, @mr int
DECLARE @first datetime, @last datetime
DECLARE @name nvarchar(60)
DECLARE @UserTable TABLE(
ID int,
Name nvarchar(60)
)
INSERT INTO @UserTable (ID, Name) VALUES (1, 'Tester');
INSERT INTO @UserTable (ID, Name) VALUES (2, 'Dummy');
INSERT INTO @UserTable (ID, Name) VALUES (3, 'User');
DECLARE @SampleTable TABLE(
A_Termin_AE int,
A_Termin_Status int,
A_Termin_Set_Date datetime
)
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 603, CAST('20090525' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 601, Cast('20090512' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 603, Cast('20090525' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 603, Cast('20100803' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 603, Cast('20100805' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 603, Cast('20100817' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (1, 601, Cast('20110521' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 601, Cast('20090501' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20090502' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20100815' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20110501' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20110505' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20110508' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20110510' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (2, 603, Cast('20110514' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20120503' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20120508' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20120510' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20120514' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20120520' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 601, Cast('20130701' AS Datetime));
INSERT INTO @SampleTable (A_Termin_AE, A_Termin_Status, A_Termin_Set_Date) VALUES (3, 603, Cast('20130703' AS Datetime));
DECLARE @TempTable TABLE(
ID int,
UserID int,
Name nvarchar(60),
Record int,
Datum datetime
)
INSERT INTO @TempTable (ID, UserID, Name, Record, Datum) VALUES (1, 0, '', 0, GETDATE());
SET @first = CAST('20080101' AS Datetime);
WHILE @first < GETDATE()
BEGIN
SET @first = dateadd(month, 1, @first)
SET @last = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@first)+1,0));
DECLARE User_Cur CURSOR
FOR SELECT tu.Id, tu.Name FROM @UserTable tu
OPEN User_Cur;
FETCH NEXT FROM User_Cur INTO @id, @name;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @mr = (SELECT COUNT(t.A_Termin_Set_Date)
FROM @SampleTable t
WHERE t.A_Termin_AE = @id
AND t.A_Termin_Status = 603
AND t.A_Termin_Set_Date BETWEEN @first AND @last);
IF (SELECT Record FROM @TempTable WHERE ID = 1) < @mr
BEGIN
UPDATE @TempTable
SET UserID = @id,
Name = @name,
Record = @mr,
Datum = @first
WHERE ID = 1;
END
FETCH NEXT FROM User_Cur INTO @id, @name;
END
CLOSE User_Cur;
DEALLOCATE User_Cur;
END
SELECT * FROM @TempTable;
因此,一个月内拨打电话次数最多的用户是: 'Dummy'在2011年5月有5个唱片;
我感谢您提供的任何帮助和建议。
答案 0 :(得分:1)
示例数据包含不同月份中具有相同最大计数的2个用户。那你为什么只列出1?你怎么知道有超过1,它可能是4或2或37。
SELECT
Name
, Mnth
, Record
, dense_rank() over(ORDER BY record DESC) RNK
FROM (
SELECT
Name
, Mnth
, Record
, dense_rank() over(ORDER BY record DESC) RNK
FROM (
SELECT
tu.Name
, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.A_Termin_Set_Date), 0) AS Mnth
, COUNT(t.A_Termin_AE) AS Record
FROM @SampleTable t
JOIN @UserTable tu ON tu.Id = t.A_Termin_AE
WHERE t.A_Termin_Status = 603
GROUP BY tu.Name, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.A_Termin_Set_Date), 0)
) d1
) d2
WHERE rnk = 1
ORDER BY Mnth DESC, Name
<强>结果:强>
Name Mnth Record RNK
------- --------------------- -------- -----
User 01.05.2012 00:00:00 5 1
Dummy 01.05.2011 00:00:00 5 1
答案 1 :(得分:0)
好的,我刚和朋友聊天,他向我解释了一个非常简单,快捷,简单的方法。如果有人遇到同样的问题,这就是答案:
SELECT TOP(1) COUNT(t.A_Termin_AE) AS Record
, tu.Name
, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.A_Termin_Set_Date), 0) AS Datum
FROM @SampleTable t
JOIN @UserTable tu ON tu.Id = t.A_Termin_AE
WHERE t.A_Termin_Status = 603
GROUP BY tu.Name, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.A_Termin_Set_Date), 0)
ORDER BY Record DESC;
再次感谢所有帮助!!!
答案 2 :(得分:0)
我必须同意@Used_By_Already。
在没有嵌套SQL语句的情况下,我使用多CTE方法做了类似的事情:
...
;WITH counting_records AS (
SELECT tu.name,
DATEADD(MONTH, DATEDIFF(MONTH, 0, st.A_Termin_Set_Date), 0) AS month,
COUNT(st.A_Termin_AE) AS record
FROM @SampleTable st
INNER JOIN @UserTable tu ON tu.Id = st.A_Termin_AE
WHERE st.A_Termin_Status = 603
GROUP BY tu.Name, DATEADD(MONTH, DATEDIFF(MONTH, 0, st.A_Termin_Set_Date), 0)
), get_rank (name, month, record, rank) AS (
SELECT cr.name,
cr.month,
cr.record,
DENSE_RANK() OVER( ORDER BY cr.record DESC) AS rank
FROM counting_records AS cr
)
-- getting the highest count (lowest rank)
SELECT get_rank.name,
get_rank.month,
get_rank.record,
get_rank.rank
FROM get_rank
WHERE get_rank.rank = 1
ORDER BY get_rank.month
结果:
name month record rank
Dummy 2011-05-01 00:00:00.000 5 1
User 2012-05-01 00:00:00.000 5 1
我认为解释DENSE_RANK() OVER(ORDER BY cr.record DESC) AS rank
也很好。
DENSE_RANK()
...返回a分区内的行级别 结果集,排名没有任何差距。
Syntax: `DENSE_RANK ( ) OVER ( [ <partition_by_clause> ] < order_by_clause > )`