如何使用 SQL select 最高和第二高字段值之间的差异?
How can I select the difference between the highest and second highest field value using SQL?
我有一个table如下:
id, party, constituency, votes
英国各选区都有记录,数据示例为:
1, Conservative, Carlisle, 21780
2, Labour, Carlisle, 18932
3, Green, Carlisle, 2310
4, Conservative, Kensington, 22098
5, Labour, Kensington, 22056
6, Green, Kensington, 3209
7, Conservative, Islington, 32908
8, Labour, Islington, 33005
9, Green, Islington, 5409
我想确定最低(和最多)多数存在的席位。例如,对于给定的选区,我想 select 所有字段,其中最大选票和第二名选票之间的差异小于 50。所以我试过了:
SELECT *,
max.votes as max,
second_max.votes as max2
FROM election
WHERE (max - max2) < 50
ORDER BY votes DESC
不用说这行不通。请问你能帮忙吗?
这是你想要的吗?
select *
from (
select
e.*,
row_number() over(partition by constituency order by votes desc) rn
from election e
) t
where
rn in (1, 2)
and max(votes) over(partition by constituency)
- min(votes) over(partition by constituency) < 50
当且仅当它们之间的差异小于 50 时,此查询为您提供每个 constituency
最高 votes
的 2 条记录。
注意:只要您的 RDMBS 支持 window 函数(MySQL < 8.0 是一个明显的例外),它就可以工作。
您可以使用 window 函数,但我会使用条件聚合:
select constituency,
max(votes) as max_votes, min(votes) as second_place
from (select e.*,
row_number() over (partition by constituency order by votes desc) as seqnum
from election e
) e
where seqnum in (1, 2)
group by consistuency
having min(votes) > max(votes) - 50;
此查询使用条件聚合而不是窗口函数解决了问题。我使用 GMB 的部分查询来提出这个解决方案:
select constituency, max(votes) as maxvotes, min(votes) as minvotes from (
select
e.*,
row_number() over(partition by constituency order by votes desc) rnk
from election e ) as x
where
rnk in (1, 2)
group by constituency
having min(votes) > max(votes) - 50
对于 ROW_NUMBER
不存在但 EXISTS
存在的数据库?
EXISTS
可用于获取分区内的前 N 个。
然后您可以汇总前 2 个组。
SELECT constituency
, MAX(votes) AS votes1
, MIN(votes) AS votes2
, MAX(votes)-MIN(votes) AS votes_diff
FROM election e
WHERE EXISTS
(
SELECT 1
FROM election e2
WHERE e2.constituency = e.constituency
AND e2.votes > e.votes
HAVING COUNT(*) < 2
)
GROUP BY constituency
HAVING (MAX(votes) - MIN(votes)) < 50
ORDER BY votes_diff DESC;
使用此示例数据:
CREATE TABLE election (
party varchar(30) not null,
constituency varchar(30) not null,
votes numeric(10) not null
);
INSERT INTO election (party, constituency, votes) VALUES
('Conservative', 'Carlisle', 21780),
('Labour', 'Carlisle', 18932),
('Green', 'Carlisle', 2310),
('Conservative', 'Kensington', 22098),
('Labour', 'Kensington', 22056),
('Green', 'Kensington', 3209),
('Conservative', 'Islington', 32908),
('Labour', 'Islington', 33005),
('Green', 'Islington', 5409);
Returns:
constituency votes1 votes2 votes_diff
Kensington 22098 22056 42
我有一个table如下:
id, party, constituency, votes
英国各选区都有记录,数据示例为:
1, Conservative, Carlisle, 21780
2, Labour, Carlisle, 18932
3, Green, Carlisle, 2310
4, Conservative, Kensington, 22098
5, Labour, Kensington, 22056
6, Green, Kensington, 3209
7, Conservative, Islington, 32908
8, Labour, Islington, 33005
9, Green, Islington, 5409
我想确定最低(和最多)多数存在的席位。例如,对于给定的选区,我想 select 所有字段,其中最大选票和第二名选票之间的差异小于 50。所以我试过了:
SELECT *,
max.votes as max,
second_max.votes as max2
FROM election
WHERE (max - max2) < 50
ORDER BY votes DESC
不用说这行不通。请问你能帮忙吗?
这是你想要的吗?
select *
from (
select
e.*,
row_number() over(partition by constituency order by votes desc) rn
from election e
) t
where
rn in (1, 2)
and max(votes) over(partition by constituency)
- min(votes) over(partition by constituency) < 50
当且仅当它们之间的差异小于 50 时,此查询为您提供每个 constituency
最高 votes
的 2 条记录。
注意:只要您的 RDMBS 支持 window 函数(MySQL < 8.0 是一个明显的例外),它就可以工作。
您可以使用 window 函数,但我会使用条件聚合:
select constituency,
max(votes) as max_votes, min(votes) as second_place
from (select e.*,
row_number() over (partition by constituency order by votes desc) as seqnum
from election e
) e
where seqnum in (1, 2)
group by consistuency
having min(votes) > max(votes) - 50;
此查询使用条件聚合而不是窗口函数解决了问题。我使用 GMB 的部分查询来提出这个解决方案:
select constituency, max(votes) as maxvotes, min(votes) as minvotes from (
select
e.*,
row_number() over(partition by constituency order by votes desc) rnk
from election e ) as x
where
rnk in (1, 2)
group by constituency
having min(votes) > max(votes) - 50
对于 ROW_NUMBER
不存在但 EXISTS
存在的数据库?
EXISTS
可用于获取分区内的前 N 个。
然后您可以汇总前 2 个组。
SELECT constituency
, MAX(votes) AS votes1
, MIN(votes) AS votes2
, MAX(votes)-MIN(votes) AS votes_diff
FROM election e
WHERE EXISTS
(
SELECT 1
FROM election e2
WHERE e2.constituency = e.constituency
AND e2.votes > e.votes
HAVING COUNT(*) < 2
)
GROUP BY constituency
HAVING (MAX(votes) - MIN(votes)) < 50
ORDER BY votes_diff DESC;
使用此示例数据:
CREATE TABLE election (
party varchar(30) not null,
constituency varchar(30) not null,
votes numeric(10) not null
);
INSERT INTO election (party, constituency, votes) VALUES
('Conservative', 'Carlisle', 21780),
('Labour', 'Carlisle', 18932),
('Green', 'Carlisle', 2310),
('Conservative', 'Kensington', 22098),
('Labour', 'Kensington', 22056),
('Green', 'Kensington', 3209),
('Conservative', 'Islington', 32908),
('Labour', 'Islington', 33005),
('Green', 'Islington', 5409);
Returns:
constituency votes1 votes2 votes_diff
Kensington 22098 22056 42