【问题标题】:MYSQL - how do i select no more than x rows max with the same field value y?MYSQL - 我如何选择不超过 x 行最大具有相同的字段值 y?
【发布时间】:2014-11-14 13:02:23
【问题描述】:

这个问题表述起来有点棘手,所以之前可能已经问过。

我正在从相互关联的数据表中选择行。我只希望在我的集合中显示最多 n 行,这些行在表中的某些字段/列中具有相同的 x 值。有一个全局限制,本质上我总是希望查询返回相同数量的行,不超过 n 行共享值 x。我该怎么做?

这是一个数据示例(点应该表示这个表很大,假设有 20000 行数据):

some_table
+----+----------+-------------+------------+
| id |  some_id | some_column | another_id |
+----+----------+-------------+------------+
|  1 |       10 |       value |          8 |
|  2 |       10 |       value |          5 |
|  3 |       10 |       value |          2 |
|  4 |       20 |       value |          3 |
|  5 |       30 |       value |          9 |
|  6 |       30 |       value |          1 |
|  7 |       30 |       value |          4 |
|  8 |       30 |       value |          6 |
|  9 |       30 |       value |          7 |
| 10 |       40 |       value |         10 |
| .. |      ... |         ... |        ... |
| .. |      ... |         ... |        ... |
| .. |      ... |         ... |        ... |
| .. |      ... |         ... |        ... |
+----+----------+-------------+------------+

现在这是我的选择:

select * from some_table where some_column="value" order by another_id limit 6

但不是返回 another_id = 1 到 6 的行,我希望得到不超过 2 行具有相同 some_id 值的行。换句话说,我想得到:

result set
+----+----------+-------------+------------+
| id |  some_id | some_column | another_id |
+----+----------+-------------+------------+
|  6 |       30 |       value |          1 |
|  3 |       10 |       value |          2 |
|  1 |       10 |       value |          3 |
|  7 |       30 |       value |          4 |
|  4 |       20 |       value |          8 |
| 10 |       40 |       value |         10 |
+----+----------+-------------+------------+

注意,结果是按another_id排序的,但是some_id值相同的结果不超过2个。

我怎样才能最好(意味着最好在一个查询中并且相当快)到达那里?谢谢!

【问题讨论】:

  • 2 是固定的还是可以用其他 k 代替 2?桌子的尺寸是多少?
  • 如上所述,k / n 是可变的。表格的大小无关紧要,但也不是固定的。

标签: mysql select subquery limit


【解决方案1】:
select id, some_id, some_column, another_id from (
    select 
    t.*,
    @rn := if(@prev = some_id, @rn + 1, 1) as rownumber,
    @prev := some_id
    from some_table t
    , (select @prev := null, @rn := 0) var_init
    where some_column="value"
    order by some_id, id
) sq where rownumber <= 2
order by another_id;
  • sqlfiddle 中实时查看它的工作情况

首先我们在子查询中按 some_id, id 排序以进行正确的计算。然后我们在外部查询中按 another_id 进行排序以得到正确的排序。

【讨论】:

  • 谢谢,这适用于我的本机排序的示例数据。无论排序如何,或者数据是否按顺序打乱或输入/添加无序,我怎样才能使其工作?
  • ...如果我能以某种方式创建一个临时数组来记录不同的、不同的 some_id 实例..?或者也许有一种方法来计算/查看已经获取的数据?
  • 已修复,请重试。
  • 谢谢,很抱歉,最初提供的示例数据没有正确说明我的问题。我现在已经更新了它,添加了另一列排序/排序必须发生。 'order by some_id' 不起作用,一旦我得到结果集,重新排序也不起作用,因为我只抓取一部分(参见上面的'limit 6')。还有其他想法吗?
  • 又更新了我的帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 2012-08-12
相关资源
最近更新 更多