我正在尝试使用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
等,但仍然没有给我正确的结果
有什么想法吗?
答案 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 < 1
和X > 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
答案 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。