首页 > 解决方案 > 如何存储 SQL 服务器查询

问题描述

我在 SQL Server 中有下表:

Date            Browser         Country         Time(ms)
----------------------------------------------------------
2019-05-06      Chrome          US              1000
2019-05-06      Chrome          US              560
2019-05-07      Firefox         JP              2300
2019-05-07      Edge            US              1200
2019-05-07      Chrome          JP              3000
2019-05-07      Chrome          JP              3200
2019-05-07      Chrome          JP              2100
2019-05-07      Firefox         US              2200

我需要根据完成时间对结果进行“分桶”。最终结果将是这样的:

Time(ms)            US              JP
--------------------------------------
0-1s                2               0
1-2s                1               0
2-3s                1               2
3+s                 0               2

我能做的最接近的事情是这样的查询:

 SELECT 
  [Country],
  COUNT(CASE WHEN [Time] >= 0 AND [Time] < 1000 THEN 1 END) AS '0 - 1s',
  COUNT(CASE WHEN [Time] >= 1000 AND [Time] < 2000 THEN 1 END) AS '1 - 2s',
  COUNT(CASE WHEN [Time] >= 2000 AND [Time] < 3000 THEN 1 END) AS '2 - 3s',
  COUNT(CASE WHEN [Time] >= 3000 THEN 1 END) AS '+3s'
  FROM [dbo].[MyTable]
  GROUP BY [Country]

但是这个模式并不是我想要的,因为我的结果是:

Country         0 - 1s      1 - 2s       2 - 3s     +3s
---------------------------------------------------------
US              2           1           1           0
JA              0           0           2           2

我应该如何解决这个问题?

标签: sql-servergrouping

解决方案


以下将为您提供一个包含国家/地区的列表,即它不会将每个国家/地区列为一列。要使每个列成为列,您要么必须做 Sticky-Bit 所做的事情,要么必须pivot- 无论哪种方式,您都必须单独处理每个国家/地区(除非您pivot使用动态 SQL 构建)。但也许您的最终用户可以使用此列表而不需要单独的列?

declare @MyTable table ([Date] date, Browser varchar(32), Country varchar(2), [Time] int)

insert into @MyTable ([Date], Browser, Country, [Time])
  select '2019-05-06',      'Chrome',          'US',              1000
  union all select '2019-05-06',      'Chrome',          'US',              560
  union all select '2019-05-07',      'Firefox',         'JP',              2300
  union all select '2019-05-07',      'Edge',            'US',              1200
  union all select '2019-05-07',      'Chrome',          'JP',              3000
  union all select '2019-05-07',      'Chrome',          'JP',              3200
  union all select '2019-05-07',      'Chrome',          'JP',              2100
  union all select '2019-05-07',      'Firefox',         'US',              2200

select Duration, Country, count(*)
from (
  select *
    , CASE WHEN [Time] >= 0 AND [Time] < 1000 THEN '0 - 1s'
    WHEN [Time] >= 1000 AND [Time] < 2000 THEN '1 - 2s'
    WHEN [Time] >= 2000 AND [Time] < 3000 THEN '2 - 3s'
    ELSE '+3s' END Duration
    , CASE WHEN [Time] >= 0 AND [Time] < 1000 THEN 0
    WHEN [Time] >= 1000 AND [Time] < 2000 THEN 1
    WHEN [Time] >= 2000 AND [Time] < 3000 THEN 2
    ELSE 3 END DurationOrder
  from @MyTable
) X
group by Duration, DurationOrder, Country
order by DurationOrder, Country

推荐阅读