SQL - 每种类型只给我 3 次点击

发布于 2024-10-13 08:50:17 字数 616 浏览 4 评论 0原文

我有某种不可能的要求:)。

我有一个表,其中一列名为 type。我想为该列中的每种类型选择 3 条记录。这可能吗?

另请注意,我使用的是 MySQL 和 Sphinx。

更新: 表结构

id       title        type
1        AAAA         string1
2        CCCC         string2
3        EEEE         string2
4        DDDD         string2
5        FFFF         string2
6        BBBB         string2
6        BBBB         string2

我希望 MySQL 返回的是(按标题排序的每种类型最多 3 条记录):

id       title        type
1        AAAA         string1
6        BBBB         string2
2        CCCC         string2
4        DDDD         string2

I have some kind of impossible request :).

I have a table where one of the columns is named type. I would like to SELECT 3 records for each type in that column. Is that possible?

Note also that I'm using MySQL and Sphinx.

UPDATE:
Table structure

id       title        type
1        AAAA         string1
2        CCCC         string2
3        EEEE         string2
4        DDDD         string2
5        FFFF         string2
6        BBBB         string2
6        BBBB         string2

What I want my MySQL to return is (up to 3 records for each type ordered by title):

id       title        type
1        AAAA         string1
6        BBBB         string2
2        CCCC         string2
4        DDDD         string2

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

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

发布评论

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

评论(4

黯然#的苍凉 2024-10-20 08:50:18

当表很大并且集合更加不可预测时,需要在内部查询中按类型对行编号进行排序,以使副作用变量发挥作用。

select id, title, type
from (select id, title, type,
        @r := CASE WHEN @g = type THEN @r+1 ELSE 1 END r,
        @g := type
      from tbl
      order by type, title) as x
where row_number <= 3
# order by type, title

如果没有两条记录在(标题、类型、id)上完全相同,则另一种不使用副作用变量的方法如下所示。这仅使用标准 ANSI SQL92 SQL。但它可能比上面的慢。

select A.id, A.title, A.type
from tbl A
left join tbl B on
   A.title = B.title and
   (A.type < B.type or
   (A.type = B.type and A.id < A.id))
group by A.id, A.title, A.type
having count(B.title) <= 2

When the table is large and collection is more unpredictable, the row numbering needs to be ordered by type in the inner query for the side-effecting variables to work.

select id, title, type
from (select id, title, type,
        @r := CASE WHEN @g = type THEN @r+1 ELSE 1 END r,
        @g := type
      from tbl
      order by type, title) as x
where row_number <= 3
# order by type, title

Another way to do this without using side effecting variables, if no two records are exactly the same on (title, type, id), is given below. This uses only standard ANSI SQL92 SQL. It may be slower than the above though.

select A.id, A.title, A.type
from tbl A
left join tbl B on
   A.title = B.title and
   (A.type < B.type or
   (A.type = B.type and A.id < A.id))
group by A.id, A.title, A.type
having count(B.title) <= 2
め七分饶幸 2024-10-20 08:50:18

查看

+--------+------------+-------+
| type   | variety    | price |
+--------+------------+-------+
| apple  | gala       |  2.79 | 
| apple  | fuji       |  0.24 | 
| apple  | limbertwig |  2.87 | 
| orange | valencia   |  3.59 | 
| orange | navel      |  9.36 | 
| pear   | bradford   |  6.05 | 
| pear   | bartlett   |  2.14 | 
| cherry | bing       |  2.55 | 
| cherry | chelan     |  6.33 | 
+--------+------------+-------+

查询:

select type, variety, price
from fruits
where (
   select count(*) from fruits as f
   where f.type = fruits.type and f.price < fruits.price
) <= 2;

Check out this article. Given:

+--------+------------+-------+
| type   | variety    | price |
+--------+------------+-------+
| apple  | gala       |  2.79 | 
| apple  | fuji       |  0.24 | 
| apple  | limbertwig |  2.87 | 
| orange | valencia   |  3.59 | 
| orange | navel      |  9.36 | 
| pear   | bradford   |  6.05 | 
| pear   | bartlett   |  2.14 | 
| cherry | bing       |  2.55 | 
| cherry | chelan     |  6.33 | 
+--------+------------+-------+

Query:

select type, variety, price
from fruits
where (
   select count(*) from fruits as f
   where f.type = fruits.type and f.price < fruits.price
) <= 2;
苍景流年 2024-10-20 08:50:17
select id, title, type
from   (select id, title, type,
               @num := if(@group = type, @num + 1, 1) as row_number,
               @group := type as dummy
        from   your_table
        order by type, title) as x
where  row_number <= 3

(使用另一篇文章 与 Martin Wickman 的答案在同一网站上!)

select id, title, type
from   (select id, title, type,
               @num := if(@group = type, @num + 1, 1) as row_number,
               @group := type as dummy
        from   your_table
        order by type, title) as x
where  row_number <= 3

(Uses a different article on the same site as Martin Wickman's answer!)

韵柒 2024-10-20 08:50:17

如果您在 (type, title) 上有索引,并且您知道 type 的可能值,我相信动态 SQL 是(一次)用于最佳表现。

对于 type 的每个可能值,为该特定类型添加 union all 和 select。最终查询将类似于以下查询:

(select * from t1 where type = 'string1' order by title limit 3)
  union all
(select * from t1 where type = 'string2' order by title limit 3)
  union all
(select * from t1 where type = 'string3' order by title limit 3);

它在包含 1,000,000 行的表上执行不到 1 秒,而其他解决方案(Martins 和 Cyber​​kiwis)大约需要 11 秒。

区别在于,上面的联合查询可以获取每种类型的前三个标题条目,然后停止,而模拟分析函数必须扫描整个表。

If you have an index on (type, title), and you know the possible values for type, I believe that dynamic SQL is the way to go (for once) for best performance.

For each possible value of type, add a union all and a select for that specific type. The final query will look like the following query:

(select * from t1 where type = 'string1' order by title limit 3)
  union all
(select * from t1 where type = 'string2' order by title limit 3)
  union all
(select * from t1 where type = 'string3' order by title limit 3);

It executes in less than 1 second on a table with 1,000,000 rows, whereas the others solutions (Martins & Cyberkiwis) takes roughly 11 seconds.

The difference is because the unioned query above can fetch the first three title entries for each type and then stop, whereas the simulated analytics function has to scan the entire table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文