SELECT CASE返回累积结果

时间:2014-11-10 05:16:46

标签: mysql sql

我正在尝试使用SELECT CASE创建一个可以返回累积结果的查询。

这是我的查询,它有效,但不会返回正确的结果。

  SELECT total, count(*) as count FROM
                       (
                         SELECT case
                         WHEN ( X ) < 1 THEN '1 km'
                         WHEN ( X ) < 3 THEN '3 km'
                         WHEN ( X ) < 5 THEN '5 km'
                         WHEN ( X ) < 10 THEN '10 km'
                         WHEN ( X ) < 15 THEN '15 km'
                         WHEN ( X ) < 25 THEN '25 km'
                         WHEN ( X ) < 50 THEN '50 km'
                         WHEN ( X ) < 100 THEN '100 km'
                         WHEN ( X ) > 0 THEN '-1'
                         else '-2'
                         end AS `total` 
                         FROM `store` AS d WHERE d.pending!='1' 
                    ) AS someRandomAliasHere
                    GROUP BY `total`

X是我用来从lat和lang计算半径的公式。 total不是我数据库表中的一列,只是计算X的结果

上面的查询给了我这个..

 1 km (4)
 3 km (19)
 5 km (103)
 25 km  (540)
 50 km (61)
 ....

4,19,103,540,62是找到的总匹配数。

3的总人数应为19+4=23 5应为103+19+4=122等。WHEN ( X ) > 0 THEN '-1'应显示总计数。比赛

我尝试使用BETWEEN 0 AND 1, BETWEEN 0 AND 3等,但仍然没有给我正确的结果

有什么想法吗?

9 个答案:

答案 0 :(得分:3)

另一种方法是独立计算结果然后将它们结合起来:

SELECT 1 AS total, COUNT(*) AS cnt FROM `store` WHERE store.pending != 1 AND ( X ) < 1
UNION ALL
SELECT 3 AS total, COUNT(*) AS cnt FROM `store` WHERE store.pending != 1 AND ( X ) < 3
UNION ALL
SELECT 5 AS total, COUNT(*) AS cnt FROM `store` WHERE store.pending != 1 AND ( X ) < 5
UNION ALL
/** ... **/
SELECT 100 AS total, COUNT(*) AS cnt FROM `store` WHERE store.pending != 1 AND ( X ) < 100

答案 1 :(得分:2)

除了积累之外,您还希望最后的总值为-1。这有点痛苦,但可以实现。

在MySQL中进行累积求和的最简单方法是使用变量。基本思路是:

 SELECT total, cnt, (@cnt := @cnt + cnt) as count  
 FROM (SELECT (case  WHEN ( X ) < 1 THEN '1'
                     WHEN ( X ) < 3 THEN '3'
                     WHEN ( X ) < 5 THEN '5'
                     WHEN ( X ) < 10 THEN '10'
                     WHEN ( X ) < 15 THEN '15'
                     WHEN ( X ) < 25 THEN '25'
                     WHEN ( X ) < 50 THEN '50'
                     WHEN ( X ) < 100 THEN '100'
                     WHEN ( X ) > 0 THEN '-1'
                     else '-2'
               end) AS total, COUNT(*) as cnt
        FROM store s
        WHERE s.pending <> '1' 
        GROUP BY total
       ) t CROSS JOIN
       (SELECT @cnt := 0) vars
  ORDER BY total;

这个问题是你不会得到总的非负值。我假设你没有负面价值。这需要在总行中添加另一行:

 SELECT total, cnt, (@cnt := @cnt + cnt) as count
 FROM (SELECT (case  WHEN ( X ) < 1 THEN '1'
                     WHEN ( X ) < 3 THEN '3'
                     WHEN ( X ) < 5 THEN '5'
                     WHEN ( X ) < 10 THEN '10'
                     WHEN ( X ) < 15 THEN '15'
                     WHEN ( X ) < 25 THEN '25'
                     WHEN ( X ) < 50 THEN '50'
                     WHEN ( X ) < 100 THEN '100'
                     WHEN ( X ) > 0 THEN '-1'
                     else '-2'
               end) AS total, COUNT(*) as cnt
        FROM store s
        WHERE s.pending <> '1' 
        GROUP BY `total`
        UNION ALL
        SELECT -1, 0
       ) t CROSS JOIN
       (SELECT @cnt := 0) vars
  ORDER BY (total >= 0) desc, total;

我也改变了order by。请注意,值-2可能毫无意义,因为X < 1X > 0涵盖X的所有可能值(NULL除外)。如果您实际上具有100或更高的值,则可以进行一些小的更改以优化查询。您没有描述如何处理这些值,因此对该问题的澄清会有所帮助。

答案 2 :(得分:1)

不确定这是否有效,因为我没有数据库来测试它。也不完全符合你想要的格式。

select sum(if(X<1,1,0)) as C1,
       sum(if(X<3,1,0)) as C3,
       sum(if(X<5,1,0)) as C5,
       sum(if(X<10,1,0)) as C10,
       sum(if(X<15,1,0)) as C15,
       sum(if(X<25,1,0)) as C25,
       sum(if(X<50,1,0)) as C50,
       sum(if(X<100,1,0)) as C100,
       sum(if(X>=100,1,0)) as C100P
from store
where store.pending != '1'

答案 3 :(得分:1)

不幸的是,MySQL没有分析函数和窗口函数,但在这种情况下,您可以使用变量和嵌套子查询来实现目标:

SELECT
  total,
  cnt,
  @rollupCount:=@rollupCount+cnt AS rollupCount
FROM
  (
    SELECT
      total,
      count(*) AS cnt
    FROM
    (
         SELECT
            CASE
             WHEN ( X ) < 1 THEN '1'
             WHEN ( X ) < 3 THEN '3'
             WHEN ( X ) < 5 THEN '5'
             WHEN ( X ) < 10 THEN '10'
             WHEN ( X ) < 15 THEN '15'
             WHEN ( X ) < 25 THEN '25'
             WHEN ( X ) < 50 THEN '50'
             WHEN ( X ) < 100 THEN '100'
             WHEN ( X ) > 0 THEN '-1'
             ELSE '-2'
           END AS `total` 
         FROM
           `store` AS d
         WHERE
           d.pending != '1' 
    ) AS someRandomAliasHere
    GROUP BY
      `total`
  ) AS anotherRandomAliasHere
  , (SELECT @rollupCount:=0) AS RC
ORDER BY
  total ASC

这与您想要计算每条记录的行号时相同:

SELECT
  @rowNumber:=@rowNumber+1 AS rowNumber,
  sourceColumns
FROM
  sourceTable, (SELECT @rowNumber:=0) AS t
ORDER BY
  orderColumn;

答案 4 :(得分:1)

可以相对简单地创建一个从现有查询中提供累积总计的列:

SELECT X,
       total,
       (SELECT SUM(total)
        FROM (<<<your_current_query>>>) ycq2
        WHERE ycq2.X <= ycq1.X) `cumulative_total`
FROM (<<<your_current_query>>>) ycq1

当在两个标记的位置粘贴当前查询时,这将会扩展很多。

请参阅SQL fiddle demo

答案 5 :(得分:1)

试试这个:

/sql server version/
DECLARE @GROUPS TABLE (TOTAL INT)
INSERT INTO @GROUPS
VALUES (1),
       (3),
       (5),
       (10),
       (15),
       (25),
       (50),
       (100),
       (-1)

SELECT a.TOTAL, z.[COUNT] FROM @GROUPS a CROSS APPLY (SELECT COUNT(*) as [COUNT] FROM store x WHERE CASE WHEN a.TOTAL = -1 THEN -x.X ELSE x.X END < REPLACE(a.TOTAL,-1,0) AND pending != 1) z

/mysql version/

CREATE TEMPORARY TABLE GROUPS TABLE (TOTAL INT) INSERT INTO GROUPS VALUES (1), (3), (5), (10), (15), (25), (50), (100), (-1)

SELECT a.TOTAL, z.[COUNT] FROM GROUPS a CROSS APPLY (SELECT COUNT(*) as [COUNT] FROM store x WHERE CASE WHEN a.TOTAL = -1 THEN -x.X ELSE x.X END < REPLACE(a.TOTAL,-1,0) AND pending != 1) z

答案 6 :(得分:1)

你的问题有点难以理解。这是你想要的吗?

CREATE TABLE Totals (X INT, SUM INT);

INSERT INTO Totals VALUES
(1, 4),
(3, 19),
(5,  103),
(25, 540),
(50, 61)

SELECT first.X
, Sum(second.SUM)
FROM Totals first
JOIN Totals second
ON first.x >= second.x
GROUP BY first.X
UNION
SELECT 0, SUM(sum) * 2
FROM Totals

http://sqlfiddle.com/#!3/65665/12

答案 7 :(得分:1)

试试这个:

1。)“THEN”之后的值必须是数字

2。)创建具有运行id的临时表(SQL SERVER的示例)

SELECT  identity(int, 1, 1) as id,
        case
        WHEN ( X ) < 1 THEN 1
        WHEN ( X ) < 3 THEN 3
        WHEN ( X ) < 5 THEN 5
        WHEN ( X ) < 10 THEN 10
        WHEN ( X ) < 15 THEN 15
        WHEN ( X ) < 25 THEN 25
        WHEN ( X ) < 50 THEN 50
        WHEN ( X ) < 100 THEN 100
        WHEN ( X ) > 0 THEN -1
        else '-2' end AS total
Into storeID
FROM store AS d 
WHERE d.pending!='1' 
Order BY total

3。)使用相同的表连接表,条件为

Select a.*, sum(b.total) as NewTotal
From storeID a
Left Join storeID b
    On b.id <= a.id
Group By a.id, a.total

4。)我认为,“NewTotal”就是你要找的东西

答案 8 :(得分:1)

我认为你的X函数返回一个浮点数。如果我正确理解您的逻辑,您希望将X为>=0 and <1,其中X >=0 and <3>=0 and <5等的值组合在一起,并且当值为0时您希望返回-1 >=0和-2,当值为负<0时。

我会使用intervals表,定义如下:

CREATE TABLE intervals (
  i_begin INT,
  i_end INT,
  i_value INT
);

INSERT INTO intervals VALUES
(0,    1,     1),
(0,    3,     3),
(0,    5,     5),
(0,    10,   10),
(0,    15,   15),
(0,    25,   25),
(0,    50,   50),
(0,    100, 100),
(0,    null, -1),
(null, 0,    -2);

或者您可以使用此表中的值来满足您的需求。

然后你可以使用INNER JOIN和GROUP BY查询:

SELECT
  i_value, COUNT(*)
FROM
  store INNER JOIN intervals
  ON ((i_begin IS NULL OR X>=i_begin) AND (i_end IS NULL OR X<i_end))
WHERE
  store.pending<>1
GROUP BY
  i_value

请参阅示例here