计算特定范围sql server的记录数

时间:2013-07-23 14:38:22

标签: sql sql-server coldfusion

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

我使用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阅读serialized文件serializeJSON。所以在数据库中,下面的所有内容都运行良好,但查询的coldfusion查询不支持CASE语句,或者它似乎不支持。

5 个答案:

答案 0 :(得分:10)

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

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的逻辑。但是,上述逻辑错过了1500130001的值。我的猜测是OP对于条件确实意味着col1 > 15000 and col1 <= 30000col1 > 30000 and col1 <= 45000。但是,我没有改变它们,因为上面是原始问题的措辞(也许1500130001有一些特别之处。

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分:1)

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

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

有点像这样:

; 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

答案 4 :(得分:0)

这样的事情怎么样?我知道它适用于&lt; 15000而不是&lt; = 15000,但如果你说的是货币金额,那么&lt; = 15000和&gt; 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