[英]SELECT CASE to return accumulative results
我正在尝试使用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
等,但它仍然没有给我正确的结果
有任何想法吗?
另一种方法是独立计算结果然后将它们结合起来:
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
。 这有点痛苦,但可以实现。
在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或更高的值,则可以进行一些小的更改以优化查询。 您没有描述如何处理这些值,因此对该问题的澄清会有所帮助。
不确定这是否有效,因为我没有数据库来测试它。 也不完全是你想要的格式。
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'
不幸的是,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;
可以相对简单地创建一个从现有查询中提供累积总计的列:
SELECT X,
total,
(SELECT SUM(total)
FROM (<<<your_current_query>>>) ycq2
WHERE ycq2.X <= ycq1.X) `cumulative_total`
FROM (<<<your_current_query>>>) ycq1
当然,当在两个标记的位置粘贴当前查询时,这将会扩展很多。
请参阅SQL小提琴演示 。
尝试这个:
/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
你的问题有点难以理解。 这是你想要的吗?
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
试试这个:
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”正是您所寻找的
我想你的X函数返回一个浮点数。 如果我正确理解你的逻辑,你想要将X >=0 and <1
值组合在一起,其中X >=0 and <3
, >=0 and <5
,依此类推,并且你想要返回-1值为>=0
,当值为负<0
时,为-2。
我会使用一个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
请在这里查看示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.