简体   繁体   English

SELECT CASE返回累积结果

[英]SELECT CASE to return accumulative results

I'm trying to create a query using SELECT CASE that would return the accumulative results. 我正在尝试使用SELECT CASE创建一个返回累积结果的查询。

Here is my query, it works but doesnt return the correct result. 这是我的查询,它可以工作,但不会返回正确的结果。

  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 is a formula i'm using to calculate radius from a lat and lang. X是我用来从lat和lang计算半径的公式。 total is NOT a column in my database table, just a result to calculations of X total不是我数据库表中的一列,只是计算X的结果

The query above gives me this.. 上面的查询给了我这个..

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

4,19,103,540,62 are the total matches found. 共有4,19,103,540,62个匹配项。

The total count for 3 should be 19+4=23 . 3的总数应为19+4=23
5 should be 103+19+4=122 etc. And WHEN ( X ) > 0 THEN '-1' should show the total count. 5应为103+19+4=122等。而WHEN ( X ) > 0 THEN '-1'应显示总计数。 of matches 比赛

I tried using BETWEEN 0 AND 1, BETWEEN 0 AND 3 etc but it still didn't give me the correct results 我尝试使用BETWEEN 0 AND 1, BETWEEN 0 AND 3等,但它仍然没有给我正确的结果

Any ideas? 有任何想法吗?

Another approach is to calculate the results independently then union them: 另一种方法是独立计算结果然后将它们结合起来:

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

In addition to the accumulation, you also want a total value at the end with -1 . 除了累积之外,您还希望最后的总值为-1 This is a bit of a pain, but it can be accomplished. 这有点痛苦,但可以实现。

The simplest way to do cumulative sums in MySQL is using variables. 在MySQL中进行累积求和的最简单方法是使用变量。 The basic idea is this: 基本的想法是这样的:

 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;

The issue with this is that you will not get an overall total of the non-negative values. 这个问题是你不会得到总的非负值。 Let me assume that you have no negative values. 我假设你没有负面价值。 This requires adding another row into the total line: 这需要在总行中添加另一行:

 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;

I've changed the order by as well. 我也改变了order by Note that the value -2 is probably meaningless, because X < 1 and X > 0 cover all possible values of X (except for NULL ). 注意,值-2可能是没有意义的,因为X < 1X > 0覆盖的所有可能值X (除了NULL )。 If you actually have values 100 or greater, there are some small changes to refine the query. 如果您实际上具有100或更高的值,则可以进行一些小的更改以优化查询。 You do not describe what to do with those values, so clarification on the question would be helpful. 您没有描述如何处理这些值,因此对该问题的澄清会有所帮助。

Not sure if this works since I don't have a database to test this on. 不确定这是否有效,因为我没有数据库来测试它。 Also not exactly in the format you want. 也不完全是你想要的格式。

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'

Unfortunatelly MySQL do not have analytical functions and windowed functions, but in this case, you can achieve your goal using a variable and a nested subquery: 不幸的是,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

This is the same as when you want to calculate the row number for each record: 这与您想要计算每条记录的行号时相同:

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

A column to give cumulative totals from an existing query can be created relatively simply: 可以相对简单地创建一个从现有查询中提供累积总计的列:

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

Of course this will expand quite a lot when pasting your current query in the two marked places. 当然,当在两个标记的位置粘贴当前查询时,这将会扩展很多。

See SQL fiddle demo . 请参阅SQL小提琴演示

try this: 尝试这个:


/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

Your question is a bit hard to understand. 你的问题有点难以理解。 Is this what you want? 这是你想要的吗?

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 http://sqlfiddle.com/#!3/65665/12

try this one : 试试这个:

1.) value after "THEN" must be numeric 1.)“THEN”之后的值必须是数字

2.) make temporary table with running id (example for SQL SERVER) 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.) join table with same table, with criteria 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.) i think, "NewTotal" is what you are looking for 4.)我认为,“NewTotal”正是您所寻找的

I suppose that you X function returns a floating point number. 我想你的X函数返回一个浮点数。 If I understand your logic correctly, you want to group together values where X is >=0 and <1 , where X >=0 and <3 , >=0 and <5 and so on, and you want to return -1 when the value is >=0 , and -2 when the value is a negative <0 number. 如果我正确理解你的逻辑,你想要将X >=0 and <1值组合在一起,其中X >=0 and <3>=0 and <5 ,依此类推,并且你想要返回-1值为>=0 ,当值为负<0时,为-2。

I would use an intervals table, defined like this: 我会使用一个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);

or you can play with values in this table to make it suite your needs. 或者您可以使用此表中的值来满足您的需求。

then you can just use an INNER JOIN and a GROUP BY query: 那么你可以使用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

Please see an example here . 在这里查看示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM