8

我正在尝试编写一个查询来计算基于多个不同范围的记录数。

我在使用 方面取得了成功union,但我觉得有更好的方法来做到这一点。

这是我所做的:

select count(col1) as range1
from tbl1
where col1 <= 15000
union
select count(col1) as range2
from tbl1
where col1 > 15001 and col1 <= 30000
union
select count(col1) as range3
from tbl1
where col1 > 30001 and col1 <= 45000
etc...

我正在使用 sql server 2008。就像我上面所说的,我很肯定有更好的方法来做到这一点,也许是这样的:sql count

编辑:是的,数据库是 sql 2008,下面的答案完全按照需要工作。我忘了提到我实际上正在阅读一个通过 coldfusion的JSON文件。所以在数据库中,下面的一切都运行良好,但是查询的冷融合查询不支持该语句,或者它似乎不支持。serializedserializeJSONCASE

4

5 回答 5

13

一种方法是使用条件求和(对于单独列中的值):

select sum(case when col1 <= 15000 then 1 else 0 end) as range1,
       sum(case when col1 > 15001 and col1 <= 30000 then 1 else 0 end) as range2,
       sum(case when col1 > 30001 and col1 <= 45000 then 1 else 0 end) as range3
from tbl1;

另一种方法是使用group by(对于单独行上的值):

select (case when col1 <= 15000 then 'range1'
             when col1 > 15001 and col1 <= 30000 then 'range2'
             when col1 > 30001 and col1 <= 45000 then 'range3'
             else 'other'
        end) as range, count(*) as cnt
from tbl1
group by (case when col1 <= 15000 then 'range1'
               when col1 > 15001 and col1 <= 30000 then 'range2'
               when col1 > 30001 and col1 <= 45000 then 'range3'
               else 'other'
          end);

我经常对这种形式使用子查询:

select range, count(*)
from (select t.*,
             (case when col1 <= 15000 then 'range1'
                   when col1 > 15001 and col1 <= 30000 then 'range2'
                   when col1 > 30001 and col1 <= 45000 then 'range3'
                   else 'other'
              end) as range
from tbl1
group by range;

这样, 的定义range只出现一次。

编辑:

以上都使用了OP的逻辑。但是,上述逻辑忽略了15001和的值30001。我的猜测是 OP 真的意味着col1 > 15000 and col1 <= 30000col1 > 30000 and col1 <= 45000条件。15001但是,我不会更改它们,因为以上是原始问题的措辞方式(也许and有一些特别之处30001)。

于 2013-07-23T14:42:02.210 回答
5

就我个人而言,我更喜欢使用派生(或物理)表来存储我的范围边界,然后我将其加入以找到我的结果。

如果需要,我认为代码更简单,更容易扩展

有点像这样:

; WITH ranges (lbound, ubound) AS (
  SELECT 0, 1500
  UNION ALL SELECT 1500, 3000
  UNION ALL SELECT 3000, 4500
)
SELECT ranges.lbound
     , ranges.ubound
     , Count(your_table.value) As turtle
FROM   ranges
 LEFT
  JOIN your_table
    ON your_table.value >= ranges.lbound
   AND your_table.value <  ranges.ubound
GROUP
    BY ranges.lbound
     , ranges.ubound
于 2013-07-23T14:56:33.030 回答
3

怎么样;

select
  count(case when col1 < 15000 then 1 else null end),
  count(case when col1 > 15001 and col1 <= 30000 then 1 else null end),
  count(case when col1 > 30001 and col1 <= 45000 then 1 else null end),
  ...
from tbl
于 2013-07-23T14:42:25.547 回答
1

作为联合中的第一个查询,您的列都将被称为“range1”。

select count(col1) as range1
from tbl1
where 
col1 <= 15000
or
(col1 > 15001 and col1 <= 30000)
or
(col1 > 30001 and col1 <= 45000)

如果你想要单独的列,你会喜欢这样的东西

SELECT sum(CASE WHEN col1 <= 15000 THEN 1 ELSE 0) range1,
sum(CASE WHEN (col1 > 15001 and col1 <= 30000) THEN 1 ELSE 0) range2,
sum(CASE WHEN (col1 > 30001 and col1 <= 45000) THEN 1 ELSE 0) range3
from tbl1
于 2013-07-23T14:45:33.143 回答
1

这样的事情怎么样?我知道它的结果是 < 15000 而不是 <= 15000,但是如果您说的是货币金额之类的东西,那么 <= 15000 和 > 15001 会错过这些值之间的任何内容。如果值非常大,您可以谈论编写很多范围。这也使得添加其他分组变得容易。

select cast([amount] as bigint) / 15000 * 15000, count(*)
from [transactions]
group by cast([amount] as bigint) / 15000
order by cast([amount] as bigint) / 15000
于 2017-11-29T22:28:52.033 回答