SQL 如何计算行中至少有 1、5、10、20 等笔交易的信用卡数量
SQL how to count the number of credit cards that had at least 1,5,10,20 etc transactions in rows
我有一个 MySQL 信用卡交易数据集。
create table trans (
card_id int,
amount int
);
insert into trans values (1, 1);
insert into trans values (2, 1);
insert into trans values (3, 1);
insert into trans values (4, 1);
insert into trans values (5, 1);
insert into trans values (5, 1);
insert into trans values (6, 1);
insert into trans values (6, 1);
insert into trans values (7, 1);
insert into trans values (7, 1);
insert into trans values (8, 1);
insert into trans values (8, 1);
insert into trans values (8, 1);
insert into trans values (9, 1);
insert into trans values (9, 1);
insert into trans values (9, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
我想知道:
1. how many cards were used to make at least 1 transaction
2. how many cards were used to make at least 5 transactions
3. how many cards were used to make at least 10 transactions
4. how many cards were used to make at least 20 transactions
etc...
由于组重叠,条件聚合似乎是更好的方法:
select sum(cnt >= 1) as trans_1,
sum(cnt >= 5) as trans_5,
sum(cnt >= 10) as trans_10,
sum(cnt >= 20) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d;
问题是上面的结果集按列生成,但我试图按行生成结果集。
MySQL 中将列转换为行的传统方法是重复使用来自 table 并集的 select sum() 序列,但在这种情况下,基础数据是一个派生的 table,所以这个方法在这里似乎不起作用。关于如何将列翻转为行的任何想法?
您可以通过在计算后旋转行或在单独的行上进行计算来执行此操作。第一个应该有更好的性能:
select x.which,
(case when x.n = 1 then trans_1
when x.n = 2 then trans_5
when x.n = 3 then trans_10
when x.n = 4 then trans_20
end) as numtransactions
from (select sum(cnt >= 1) as trans_1,
sum(cnt >= 5) as trans_5,
sum(cnt >= 10) as trans_10,
sum(cnt >= 20) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
) d join
(select 1 as n, '1 or more' as which union all
select 2, '5 or more' union all
select 3, '10 or more' union all
select 4, '20 or more'
) x
order by x.n;
这是一个简单的答案,但它确实有效。它不太理想,因为需要多次执行查询才能进行分组和计数。
select sum(cnt >= 1) as trans_1
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 2) as trans_2
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 3) as trans_10
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 4) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d;
我有一个 MySQL 信用卡交易数据集。
create table trans (
card_id int,
amount int
);
insert into trans values (1, 1);
insert into trans values (2, 1);
insert into trans values (3, 1);
insert into trans values (4, 1);
insert into trans values (5, 1);
insert into trans values (5, 1);
insert into trans values (6, 1);
insert into trans values (6, 1);
insert into trans values (7, 1);
insert into trans values (7, 1);
insert into trans values (8, 1);
insert into trans values (8, 1);
insert into trans values (8, 1);
insert into trans values (9, 1);
insert into trans values (9, 1);
insert into trans values (9, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
insert into trans values (10, 1);
我想知道:
1. how many cards were used to make at least 1 transaction
2. how many cards were used to make at least 5 transactions
3. how many cards were used to make at least 10 transactions
4. how many cards were used to make at least 20 transactions
etc...
由于组重叠,条件聚合似乎是更好的方法:
select sum(cnt >= 1) as trans_1,
sum(cnt >= 5) as trans_5,
sum(cnt >= 10) as trans_10,
sum(cnt >= 20) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d;
问题是上面的结果集按列生成,但我试图按行生成结果集。
MySQL 中将列转换为行的传统方法是重复使用来自 table 并集的 select sum() 序列,但在这种情况下,基础数据是一个派生的 table,所以这个方法在这里似乎不起作用。关于如何将列翻转为行的任何想法?
您可以通过在计算后旋转行或在单独的行上进行计算来执行此操作。第一个应该有更好的性能:
select x.which,
(case when x.n = 1 then trans_1
when x.n = 2 then trans_5
when x.n = 3 then trans_10
when x.n = 4 then trans_20
end) as numtransactions
from (select sum(cnt >= 1) as trans_1,
sum(cnt >= 5) as trans_5,
sum(cnt >= 10) as trans_10,
sum(cnt >= 20) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
) d join
(select 1 as n, '1 or more' as which union all
select 2, '5 or more' union all
select 3, '10 or more' union all
select 4, '20 or more'
) x
order by x.n;
这是一个简单的答案,但它确实有效。它不太理想,因为需要多次执行查询才能进行分组和计数。
select sum(cnt >= 1) as trans_1
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 2) as trans_2
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 3) as trans_10
from (select card_id, count(*) as cnt
from trans
group by card_id
) d
UNION ALL
select sum(cnt >= 4) as trans_20
from (select card_id, count(*) as cnt
from trans
group by card_id
) d;