MySQL 基于 GROUP BY SELECT n 条记录

发布于 2024-10-12 07:04:53 字数 318 浏览 7 评论 0原文

假设我有 SQL 记录:

Country | Number
USA | 300
USA | 450
USA | 500
USA | 100
UK  | 300
UK  | 400
UK  | 1000

我正在做这样的事情:SELECT * FROM table GROUP BY Country
如果我想选择只显示每个国家中 2 个最大数字的结果怎么办?我怎样才能存档这个?

结果将是:

Country | Number
USA | 450
USA | 500
UK  | 400
UK  | 1000

Lets say I have SQL records:

Country | Number
USA | 300
USA | 450
USA | 500
USA | 100
UK  | 300
UK  | 400
UK  | 1000

And I am doing something like this: SELECT * FROM table GROUP BY Country.
What if, I want to choose to display the result with 2 greatest number only in each country? How can I archive this?

The result would be:

Country | Number
USA | 450
USA | 500
UK  | 400
UK  | 1000

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

随波逐流 2024-10-19 07:04:53

示例数据

create table data (Country varchar(10), Number int);
insert into data select
'USA' , 300 union all select
'USA' , 450 union all select
'USA' , 500 union all select
'USA' , 100 union all select
'FR'  , 100 union all select
'FR'  , 420 union all select
'UK'  , 300 union all select
'UK'  , 400 union all select
'UK'  , 1000;

第一个选项是使用像 Scrum Meister 所示的变量的伪排名,但在这里作为单个语句呈现

SELECT Country, Number
FROM (
    SELECT
        Number,
        @r := case when @c=country then @r+1 else 1 end rownum,
        @c := Country Country 
    FROM (select @r :=0 , @c := '') x, data
    ORDER BY Country, Number DESC
) y
WHERE rownum < 3;

如果您在前端使用它,并且只需要 2 个计数,那么您可以使用此形式返回列表中的计数(单列)

SELECT
    Country,
    left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers
FROM (
    SELECT
        a.Country,
        Group_Concat(a.Number) x
    From (
        select country, number
        from data
        order by country, number desc) a
    group by a.Country
) b

结果是

"Country";"Numbers"
"FR";"420,100"
"UK";"1000,400"
"USA";"500,450"

如果有可能出现平局,则第二种形式的这种变体将删除平局并显示“每个国家/地区前 2 个不同的数字”作为记录。

SELECT distinct x.Country, x.Number
From data x
inner join
(
    SELECT
        Country,
        left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers
    FROM (
        SELECT
            a.Country,
            Group_Concat(a.Number) x
        From (
            select distinct country, number
            from data
            order by country, number desc) a
        group by a.Country
    ) b
) y on x.Country=y.Country
    and concat(',',y.Numbers,',') like concat('%,',x.Number,',%')
order by x.Country, x.Number Desc

结果

"Country";"Number"
"FR";"420"
"FR";"100"
"UK";"1000"
"UK";"400"
"USA";"500"
"USA";"450"

Sample data

create table data (Country varchar(10), Number int);
insert into data select
'USA' , 300 union all select
'USA' , 450 union all select
'USA' , 500 union all select
'USA' , 100 union all select
'FR'  , 100 union all select
'FR'  , 420 union all select
'UK'  , 300 union all select
'UK'  , 400 union all select
'UK'  , 1000;

The first option is a pseudo rank using variables like The Scrum Meister has shown, but presented here as a single statement

SELECT Country, Number
FROM (
    SELECT
        Number,
        @r := case when @c=country then @r+1 else 1 end rownum,
        @c := Country Country 
    FROM (select @r :=0 , @c := '') x, data
    ORDER BY Country, Number DESC
) y
WHERE rownum < 3;

If you are using this in a front end, and only need 2 counts, then you can use this form that returns the counts in a list (single column)

SELECT
    Country,
    left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers
FROM (
    SELECT
        a.Country,
        Group_Concat(a.Number) x
    From (
        select country, number
        from data
        order by country, number desc) a
    group by a.Country
) b

The result is

"Country";"Numbers"
"FR";"420,100"
"UK";"1000,400"
"USA";"500,450"

If it is possible for ties to occur, then this variation of the 2nd form removes the ties and shows the "top 2 distinct numbers per country", as records.

SELECT distinct x.Country, x.Number
From data x
inner join
(
    SELECT
        Country,
        left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers
    FROM (
        SELECT
            a.Country,
            Group_Concat(a.Number) x
        From (
            select distinct country, number
            from data
            order by country, number desc) a
        group by a.Country
    ) b
) y on x.Country=y.Country
    and concat(',',y.Numbers,',') like concat('%,',x.Number,',%')
order by x.Country, x.Number Desc

Result

"Country";"Number"
"FR";"420"
"FR";"100"
"UK";"1000"
"UK";"400"
"USA";"500"
"USA";"450"
帅气尐潴 2024-10-19 07:04:53

由于MySql没有内置的RANK函数,查询可能会很慢:

SET @cRank = 0;
SET @cCoutnry = '';

SELECT Country, Number
FROM (
    SELECT Number, @cRank := IF(@cCoutnry = Country, @cRank+1, 1) AS rank, @cCoutnry := Country Country 
    FROM table
    ORDER BY Country, Number DESC
) rs
WHERE rank < 3

Since MySql does not have a built in RANK function, the query may be slow:

SET @cRank = 0;
SET @cCoutnry = '';

SELECT Country, Number
FROM (
    SELECT Number, @cRank := IF(@cCoutnry = Country, @cRank+1, 1) AS rank, @cCoutnry := Country Country 
    FROM table
    ORDER BY Country, Number DESC
) rs
WHERE rank < 3
尐偏执 2024-10-19 07:04:53

让我们将您的表命名为 TName,然后他们的查询将是。

SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY X.Country) AS RowNo, *
FROM (SELECT Country, Name FROM TName ORDER BY Country, Number) X ) Y WHERE Y.RowNo <= 2

Lets name your table TName, then they query would be.

SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY X.Country) AS RowNo, *
FROM (SELECT Country, Name FROM TName ORDER BY Country, Number) X ) Y WHERE Y.RowNo <= 2
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文