2012-12-23 51 views
5

我需要为每条不同的记录选择几行。尽管我使用MySQL,但在这里询问的信息几乎就是Select first n records for each distinct ID in SQL Server 2008在单个查询中为每个DISTINCT之一选择几条记录

目的可以通过在这种情况下运行21次的查询来实现:1一般20来获取子记录,即是这样的:

SELECT DISTINCT `user_id` 
FROM `posts` 
WHERE `deleted` = '0' 
ORDER BY `user_id` ASC 
LIMIT 20 

...来选择所需要的所有行,然后

SELECT * 
FROM `posts` 
WHERE `deleted` = '0' 
AND `user_id` = ? 
ORDER BY `id` DESC 
LIMIT 5 

...在由第一查询选择的每一行的循环中。

基本上,我有点需要得到每个用户的5个职位。我需要在单个查询中完成此操作。例如,posts设置就是这样,我做了这个,所以希望更容易理解我需要的东西。

我开始用下面的查询:

SELECT * 
FROM `posts` 
WHERE `user_id` 
IN (
    SELECT DISTINCT `user_id` 
    FROM `posts` 
    ORDER BY `user_id` DESC 
    LIMIT 4 
) 
LIMIT 5 

,但我得到了#1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'错误。

所以我尝试了JOIN想法类似建议here

SELECT posts.id, 
     posts.user_id, 
     NULL 
FROM (
     SELECT posts.user_id 
     FROM posts 
     WHERE posts.deleted = 0 
     LIMIT 20 
     ) q 
JOIN posts 
ON  posts.user_id = q.user_id 

我也试了几个嵌套查询的建议here

SELECT * 
FROM posts 
WHERE user_id IN (
     SELECT * FROM (
      SELECT user_id 
      FROM posts 
      LIMIT 20 
    ) 
     as t); 

而其它解决方案在因特网上找到。但是它们要么不工作,要么只是简单地从数据库中选择前N行(无论出于某种原因条件和联接)。试过LEFT JOINRIGHT JOIN,甚至INNER JOIN,但仍然没有成功。

请帮忙。

UPDATE忘了提及该表大小约为5GB。

UPDATE 试过子 - 子查询:

SELECT * 
FROM `posts` 
WHERE 
    `user_id` IN (SELECT `user_id` FROM (
    SELECT DISTINCT `user_id` 
    FROM `posts` 
    ORDER BY `user_id` DESC 
    LIMIT 4) limit_users 
) 
LIMIT 5 

与上面相同,则它返回下列:

+----+---------+------+ 
| id | user_id | post | 
+----+---------+------+ 
| 1 |  1 | a | 
+----+---------+------+ 
| 2 |  1 | b | 
+----+---------+------+ 
| 3 |  1 | c | 
+----+---------+------+ 
| .. |  .. | .. | 

即5(这是外部LIMIT设置为)同一用户的行。奇怪的是,如果我跑独子和子子查询:

SELECT `user_id` FROM (
    SELECT DISTINCT `user_id` 
    FROM `posts` 
    ORDER BY `user_id` DESC 
    LIMIT 4) limit_users 

我得到了4个不同的值:

+---------+ 
| user_id | 
+---------+ 
|  1 | 
+---------+ 
|  2 | 
+---------+ 
|  3 | 
+---------+ 
|  4 | 
+---------+ 
+1

见为首的部分**从每个组由@ BaronSchwartz的文章选择最上面的N行**,[如何选择SQL中每个组的第一/最小/最大行](http://www.xaprb.com/blog/2006/12/07/how-to-sele CT-的-firstleastmax排每组合SQL /)。 – eggyal

回答

1

你必须使用变量,对一个做两个不同的罪名订购查询:一个在岗位每个用户的数量,以及一个用于用户:

SELECT posts_counts.* 
FROM (
    SELECT 
    posts.*, 
    @post_count:=case when @prec_user_id=user_id then @post_count+1 else 1 end as pc, 
    case when @prec_user_id<>user_id then @user_count:[email protected]_count+1 else @user_count end as uc, 
    @prec_user_id:=user_id 
    FROM 
    posts, 
    (select @prec_user_id:=0, @user_count:=0, @post_count:=0) counts 
    ORDER BY 
    posts.user_id) posts_counts 
WHERE pc<5 and uc<4 

编辑:你也可以考虑尝试此查询:

SELECT * 
FROM `posts` 
WHERE 
    `user_id` IN (SELECT user_id FROM (
    SELECT DISTINCT `user_id` 
    FROM `posts` 
    ORDER BY `user_id` DESC 
    LIMIT 4) limit_users 
) 
LIMIT 5 

(这将甫一选择5个职位,在来自各选定用户的所有帖子,所以它仍然不是你所需要的,但它使用一招,用在子子查询LIMIT)

EDIT2:下一个查询将限制5个员额为每个20个用户:

select posts_limited.* 
from (
    select 
    posts.*, 
    @row:=if(@last_user=posts.user_id, @row+1, 1) as row, 
    @last_user:=posts.user_id 
    from 
    posts inner join 
    (select user_id from 
     (select distinct user_id 
     from posts 
     order by user_id desc 
     LIMIT 20) limit_users 
    ) limit_users 
    on posts.user_id = limit_users.user_id, 
    (select @last_user:=0, @row:=0) r 
) posts_limited 
    where row<=5 
+0

谢谢你的回复。这是如何在一张大桌子上工作的?这对我来说太复杂了:) –

+0

@TheSexiestManinJamaica起初看起来很复杂,但是一旦你使用变量,它应该清楚它的作用......但是在一张大桌子上它可能很慢......让我想一想关于其他一些解决方案... – fthiella

+0

谢谢,感谢。 –

相关问题