获取过去3年中每月的最大值以选择记录月

时间:2017-10-23 08:49:12

标签: sql sql-server sql-server-2012

我们正在使用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个唱片;

我感谢您提供的任何帮助和建议。

3 个答案:

答案 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 

参考:http://rextester.com/DORH41455

答案 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 > )`