4

我必须按小时对某人从特定国家/地区拨打电话的次数进行排序。国家列表按月增加,例如我们可以添加巴西。我正在使用 SQL Server。

数据看起来像这样

2012-04-02 08:00:59    United States
2012-04-02 08:12:02    United States
2012-04-02 08:13:42    Canada
2012-04-02 08:13:56    United States
2012-04-02 08:14:07    Mexico
2012-04-02 08:18:09    Canada
2012-04-02 08:19:50    United States
2012-04-02 08:34:34    Mexico
etc.

我想如何按小时列出前 2 个国家/地区的数据。

我希望它显示如下:

Date                   Country          Calls
2012-04-02 08:00:00    United States    24
2012-04-02 08:00:00    Canada           19
--hidden--
2012-04-02 08:00:00    Mexico           12

我尝试的代码(不起作用):

Declare @StartDate datetime, @EndDate datetime
    set @StartDate = '20120401 00:00:00'
  set @EndDate = '20120430 23:59:59'
SELECT  DATEADD(HOUR, DATEPART(HOUR, [date]), DATEDIFF(DAY, 0, [date])) as [date],
(SELECT COUNT([country]) FROM [mytable] WHERE [date] between @StartDate and @EndDate and [country] = 'United States' ) as [United_States]
,(SELECT COUNT([country]) FROM [mytable] WHERE [date] between @StartDate and @EndDate and [country] = 'Canada' ) as [Canada]
,(SELECT COUNT([country]) FROM [mytable] WHERE [date] between @StartDate and @EndDate and [country] = 'Mexico' ) as [Canada]
FROM [mytable] 
WHERE [date] between @StartDate and @EndDate
GROUP BY DATEADD(HOUR, DATEPART(HOUR, [date]), DATEDIFF(DAY, 0, [date]))
ORDER BY [date]

谢谢你。

4

6 回答 6

1

试试这个。也许有一些语法错误,但我认为它朝着正确的方向发展。

SELECT T1.Date, T1.Country, SUM(1)
FROM CallsTable T1
GROUP BY DATEADD(hh, DATEDIFF(hh,0,T1.Date),0), T1.Country
HAVING T1.Country IN (SELECT TOP 2 T2.Country
                      FROM CallsTable T2
                      WHERE DATEADD(hh, DATEDIFF(hh,0,T2.Date),0) = DATEADD(hh, DATEDIFF(hh,0,T1.Date),0)
                      GROUP BY T2.Country
                      ORDER BY SUM(1) DESC                    
                      )

解释:

DATEADD(hh, DATEDIFF(hh,0,T1.Date),0)截断分钟和秒,以便按小时分组。

主要按小时和国家选择组。内部选择是一个过滤器,因此仅显示指定时间的两个最高呼叫国家/地区。

于 2012-04-20T22:34:49.620 回答
1

使用cteover子句相对简单易读:

WITH CTE AS(
      SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, Date), 0)AS DateHour
    , Country
    , Count(*) OVER(Partition By Country, DATEPART(HOUR, Date))as GrpCount
    FROM @mytable
    WHERE date between @StartDate and @EndDate
)
SELECT DateHour AS Date, Country, GrpCount AS Calls
FROM CTE
GROUP BY Country, DateHour, GrpCount
ORDER BY DateHour

这是您的示例数据:

declare @myTable table(date datetime, country varchar(20));
insert into @myTable values(convert(datetime,'2012-04-02 08:00:59',102),'United States');
insert into @myTable values(convert(datetime,'2012-04-02 08:13:42',102),'Canada');
insert into @myTable values(convert(datetime,'2012-04-02 08:13:56',102),'United States');
insert into @myTable values(convert(datetime,'2012-04-02 08:14:07',102),'Mexico');
insert into @myTable values(convert(datetime,'2012-04-02 08:18:09',102),'Canada');
insert into @myTable values(convert(datetime,'2012-04-02 08:19:50',102),'United States');
insert into @myTable values(convert(datetime,'2012-04-02 08:34:34',102),'Mexico');

Declare @StartDate datetime, @EndDate datetime;
    set @StartDate = '20120401 00:00:00';
    set @EndDate = '20120430 23:59:59';

结果:

Date                      Country           Calls
2012-04-02 08:00:00.000   Canada            2
2012-04-02 08:00:00.000   Mexico            2
2012-04-02 08:00:00.000   United States     3
于 2012-04-20T22:52:28.073 回答
1

这应该这样做:

Declare @StartDate datetime, 
    @EndDate datetime
    set @StartDate = '20120401 00:00:00'
    set @EndDate = '20120430 23:59:59'

;WITH
  mytablePlusHours As
(
    SELECT *,
        DATEADD(HOUR, DATEPART(HOUR, [date]), DATEDIFF(DAY, 0, [date]))     AS [dateHour]
    FROM    [mytable]    
)
, mytableHourGroups As
(
    SELECT  dateHour, 
            country,
            COUNT(*)        As [countryCount],
            ROW_NUMBER() OVER(PARTITION BY dateHour ORDER BY countryCount) 
                            As [countryRank]
    FROM        mytablePlusHours
    GROUP BY    dateHour, country
)
SELECT  
        dateHour     AS [date],
        country,
        countryCount
FROM    mytableHourGroups
WHERE   [date] between @StartDate and @EndDate
  AND   countryRank <= 2
ORDER BY [date], countryRank
于 2012-04-20T22:58:28.710 回答
0

我相信最简单的解决方案是分两步。

首先,您必须将日期时间转换为偶数小时。通过将数据从一个表复制到另一个表或通过视图或将计算字段添加到表中来实现。

然后你做类似的事情

select date time, country, count(*) calls
from mytable
group by date, country

我不确定它是“count(*)” - 请有人纠正我。

于 2012-04-20T22:20:08.697 回答
0

添加到 Darren Davies 的答案中,您可以进一步定义表输出以按日期和时间解析:

SELECT 
  DATEADD(dd, 0, DATEDIFF(dd, 0, [Date])) as Date, 
  DATEPART(HOUR, [Date]) as Hour, 
  Country, 
  SUM(Calls)
FROM YourTable
GROUP BY 
  DATEADD(dd, 0, DATEDIFF(dd, 0, [Date])),
  DATEPART(HOUR, [Date]), 
  Country
于 2012-04-20T22:35:03.653 回答
0

未经测试:

SELECT date(yourdate) as mday, 
       datepart(hour, yourdate) as Yourhour, 
       country, 
       count(*) as calls, 
       ROW_NUMBER() OVER(PARTITION BY date(YourDate) & "-" & Datepart(hour,YourDate) & ORDER BY count(*) DESC) myCount
FROM yourTableName
GROUP BY date(yourdate), datepart(hour, yourdate)
having myCount <3
Order by count(*), mday, yourhour

不知何故 Row_NUMBER() Over (partiion By... 似乎它会给你你想要的东西'但我无法测试它。请参阅MSFT ARTICLE以了解使用情况以及为什么我认为这是你所追求的。

本质上,您希望在一天和一小时创建不同的分区,按该分区集中的调用计数排序,并为每个记录/计数分配一个从 1 开始增加 1 的数字。然后,您希望将该记录/计数限制为每天/小时分组的前 2 个。

于 2012-04-20T22:38:03.893 回答