我有以下查询,它将返回表格交易中赚取100美元到200美元的用户数
SELECT COUNT(users.id)
FROM transactions
LEFT JOIN users ON users.id = transactions.user_id
WHERE transactions.amount > 100 AND transactions.amount < 200
以上查询返回以下正确的结果:
COUNT(users.id)
559
我想扩展它,以便查询可以按以下格式返回数据:
COUNT(users.id) : amount
1678 : 0-100
559 : 100-200
13 : 200-300
我该怎么做?
答案 0 :(得分:2)
您可以在聚合函数中使用CASE表达式,该表达式将在列中获得结果:
SELECT
COUNT(case when amount >= 0 and amount <= 100 then users.id end) Amt0_100,
COUNT(case when amount >= 101 and amount <= 200 then users.id end) Amt101_200,
COUNT(case when amount >= 201 and amount <= 300 then users.id end) Amt201_300
FROM transactions
LEFT JOIN users
ON users.id = transactions.user_id;
您会注意到我更改了范围从0-100,101-200,201-300,否则您将在100,200个值上对用户ID进行两次计数。
如果您想要行中的值,则可以使用:
select count(u.id),
CASE
WHEN amount >=0 and amount <=100 THEN '0-100'
WHEN amount >=101 and amount <=200 THEN '101-200'
WHEN amount >=201 and amount <=300 THEN '101-300'
END Amount
from transactions t
left join users u
on u.id = t.user_id
group by
CASE
WHEN amount >=0 and amount <=100 THEN '0-100'
WHEN amount >=101 and amount <=200 THEN '101-200'
WHEN amount >=201 and amount <=300 THEN '101-300'
END
但是如果您需要计算多个范围,那么您可能需要考虑创建一个包含范围的表,类似于以下内容:
create table report_range
(
start_range int,
end_range int
);
insert into report_range values
(0, 100),
(101, 200),
(201, 300);
然后,您可以使用此表通过范围值连接到当前表和组:
select count(u.id) Total, concat(start_range, '-', end_range) amount
from transactions t
left join users u
on u.id = t.user_id
left join report_range r
on t.amount >= r.start_range
and t.amount<= r.end_range
group by concat(start_range, '-', end_range);
如果您不想创建包含范围的新表,则可以始终使用派生表来获得相同的结果:
select count(u.id) Total, concat(start_range, '-', end_range) amount
from transactions t
left join users u
on u.id = t.user_id
left join
(
select 0 start_range, 100 end_range union all
select 101 start_range, 200 end_range union all
select 201 start_range, 300 end_range
) r
on t.amount >= r.start_range
and t.amount<= r.end_range
group by concat(start_range, '-', end_range);
答案 1 :(得分:2)
执行此操作的一种方法是在组中使用case / when语句。
SELECT
-- NB this must match your group by statement exactly
-- otherwise you will get an error
CASE
WHEN amount <= 100
THEN '0-100'
WHEN amount <= 200
THEN '100-200'
ELSE '201+'
END Amount,
COUNT(*)
FROM
transactions
GROUP BY
CASE
WHEN amount <= 100
THEN '0-100'
WHEN amount <= 200
THEN '100-200'
ELSE '201+'
END
如果您计划在其他地方使用分组,将它定义为标量函数(它看起来也更清晰)可能是有意义的。
e.g。
SELECT
AmountGrouping(amount),
COUNT(*)
FROM
transactions
GROUP BY
AmountGrouping(amount)
如果你想完全通用:
SELECT
concat(((amount DIV 100) * 100),'-',(((amount DIV 100) + 1) * 100)) AmountGroup,
COUNT(*)
FROM
transactions
GROUP BY
AmountGroup
答案 2 :(得分:0)
比尔博,我试图发挥创造力,找到了一个非常好的解决方案[对于喜欢数学的人(像我一样)] 当MySQL整数除法运算符解决了我们的问题时,总是令人惊讶。
DROP SCHEMA IF EXISTS `stackoverflow3`;
CREATE SCHEMA `stackoverflow3`;
USE `stackoverflow3`;
CREATE TABLE users (
id INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(25) NOT NULL DEFAULT "-");
CREATE TABLE transactions(
id INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
user_id INT UNSIGNED NOT NULL,
amount INT UNSIGNED DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users (id));
INSERT users () VALUES (),(),();
INSERT transactions (user_id,amount)
VALUES (1,120),(2,270),(3, 350),
(2,500), (1,599), (1,550), (3,10),
(3,20), (3,30), (3,50), (3,750);
SELECT
COUNT(t.id),
CONCAT(
((t.amount DIV 100)*100)," to ",((t.amount DIV 100 + 1)*100-1)
) AS amount_range
FROM transactions AS t
GROUP BY amount_range;
等待你提问,巴金斯先生。