在没有游标的情况下总结SQL中的层级

时间:2012-05-11 00:13:13

标签: sql sql-server-2008 tsql

我有一个SQL服务器表,如下所示:

CREATE TABLE foo(
PlayerID BIGINT NOT NULL
UpdatedAt DATETIME NOT NULL
CurrencyBal MONEY NOT NULL)

该表包含30条记录:

1,2012-05-10,300
2,2012-05-10,1100
3,2012-05-10,10000

我想创建一个查询,它将返回播放器总数,运行查询的日期以及Currency Tiers的细分,因此输出应该只有1行,如下所示:

Date: 2012-05-10
Total Players: 3
100 - 900 : 1
999 - 1500 : 1
9000 - MAX : 1

我知道如何使用游标总计层级别我只是想知道是否有办法在没有游标的情况下执行此操作。当我尝试使用SELECT CASE时,每条记录获得1行。我已尝试通过UpdatedAt进行分组并返回相同的内容。任何帮助,将不胜感激。

使用带有以下查询的解决方案1:

SELECT 
'0 - 10000' = COUNT(CASE WHEN CreditBalance >= 0 AND CreditBalance <= 10000  THEN 1 ELSE 0 END), 
'10001 - 20000' = COUNT(CASE WHEN CreditBalance >= 10001 AND CreditBalance <= 20000 THEN 1 ELSE 0 END),
'20001 - 30000' = COUNT(CASE WHEN CreditBalance >= 20001 AND SUM(CreditBalance) <= 30000 THEN 1 ELSE 0 END), 
'30001 - 60000' = COUNT(CASE WHEN CreditBalance >= 30001 AND SUM(CreditBalance) <= 60000 THEN 1 ELSE 0 END),
'60001 - 100000' = COUNT(CASE WHEN CreditBalance >= 60001 AND SUM(CreditBalance) <= 100000 THEN 1 ELSE 0 END),
'100001 - 150000' = COUNT(CASE WHEN CreditBalance >= 100001 AND SUM(CreditBalance) <= 150000 THEN 1 ELSE 0 END), 
'150001 - 200000' = COUNT(CASE WHEN CreditBalance >= 150001 AND SUM(CreditBalance) <= 200000 THEN 1 ELSE 0 END), 
'200001 - 500000' = COUNT(CASE WHEN CreditBalance >= 200001 AND SUM(CreditBalance) <= 500000 THEN 1 ELSE 0 END),
'500001 - 1000000' = COUNT(CASE WHEN CreditBalance >= 500001 AND SUM(CreditBalance) <= 1000000 THEN 1 ELSE 0 END),
'1000001 - Max' = COUNT(CASE WHEN CreditBalance >= 1000001 THEN 1 ELSE 0 END),
CONVERT(DATE,LastUpdateDate) AS [Day],
SUM(CreditBalance) AS TotalDailyCurrency, 
COUNT(PlayerID) AS DailyActiveUsers,
AVG(CreditBalance) AS AverageCreditsPerMAU
FROM dbo.PlayerBalances
WHERE CONVERT(DATE,LastUpdateDate) = CONVERT(DATE,GETUTCDATE())
GROUP BY LastUpdateDate

我得到了:Msg 130,Level 15,State 1,Line 7 无法对包含聚合或子查询的表达式执行聚合函数。

3 个答案:

答案 0 :(得分:1)

为您提供另一种选择和小提琴。让我知道你的想法。

http://sqlfiddle.com/#!3/eed70/2

另一个替代方案,这可能会更好地扩展我最初没有注意到你有多少案例。

http://sqlfiddle.com/#!3/eed70/4

答案 1 :(得分:1)

看起来我所要做的就是从case语句中删除ELSE 0。最终解决方案如下所示:

SELECT  COUNT(CASE WHEN CreditBalance >= 0
                    AND CreditBalance <= 10000 THEN 1
          END) AS '0-10000' ,
COUNT(CASE WHEN CreditBalance >= 10001
                    AND CreditBalance <= 20000 THEN 1
          END) AS '10001 - 20000' ,
COUNT(CASE WHEN CreditBalance >= 20001
                    AND CreditBalance <= 30000 THEN 1
          END) AS '20001 - 30000' ,
COUNT(CASE WHEN CreditBalance >= 30001
                    AND CreditBalance <= 60000 THEN 1
          END) AS '30001 - 60000' ,
COUNT(CASE WHEN CreditBalance >= 60001
                    AND CreditBalance <= 100000 THEN 1
          END) AS '60001 - 100000' ,
COUNT(CASE WHEN CreditBalance >= 100001
                    AND CreditBalance <= 150000 THEN 1
          END) AS '100001 - 150000' ,
COUNT(CASE WHEN CreditBalance >= 150001
                    AND CreditBalance <= 200000 THEN 1
          END) AS '150001 - 200000' ,
COUNT(CASE WHEN CreditBalance >= 200001
                    AND CreditBalance <= 500000 THEN 1
          END) AS '200001 - 500000' ,
COUNT(CASE WHEN CreditBalance >= 500001
                    AND CreditBalance <= 1000000 THEN 1
          END) AS '500001 - 1000000' ,
COUNT(CASE WHEN CreditBalance >= 1000001 THEN 1
          END) AS '1000001 - MAX'
FROM    dbo.PlayerBalances
GROUP BY CONVERT(DATE, LastUpdateDate)

答案 2 :(得分:0)

SELECT COUNT(CASE WHEN CurrencyBal >= x_1 and CurrencyBal < x_2 THEN 1 ELSE END),
      COUNT(CASE WHEN CurrencyBal >= x_2 and CurrencyBal < x_3 THEN 1 ELSE END)
     ...., 
     UpdatedAt,
     Count(*)
     FROM Table t
     WHERE UpdatedAt = <yourdate>
     GROUP BY UpdatedAt

或者更好的方法,如果你想在表格中定义你的层级(min_range,max_range)

SELECT COUNT(CASE WHEN CurrencyBal >= min_range and CurrencyBal < max_range THEN 1 ELSE END),
     min_range,
     UpdatedAt
     FROM Table t INNER JOIN Tier ti ON CurrencyBal >= min_range and CurrencyBal < max_range 
     WHERE UpdatedAt = <yourdate>
     GROUP BY min_range,UpdatedAt