2017-02-08 8 views
0

사용자 테이블 당 제한 행MYSQL : 상기 식에서()

ID


user_comments 표

ID | user_id | 내용 |


created_at 나는 사용자 ID의 목록을 가지고 있고, 나는 각 사용자 ID에 대한 최신 3 개의 댓글을 잡고 싶다.

SELECT * FROM user_comments WHERE user_id IN (1, 2, 3, 4, 5) 
ORDER BY created_at DESC 
LIMIT 3; 

이 모든 일치하는 ID를, 내가 ID의 마지막 3 개의 댓글을 원하는 에서 마지막 3 개의 댓글을 잡아 것입니다. 하나의 유니온이없는 쿼리.

나는 그 자체로 테이블에 합류하려고 노력했지만 제대로 할 수없는 것 같습니다.

** 편집 : 주문시 ID 열에 의존 할 수 없으며 날짜 열을 사용해야합니다.

감사합니다.


** 내 최종 솔루션

SELECT user_comments.* FROM user_comments 
LEFT OUTER JOIN user_comments user_comments_2 
ON user_comments.post_id = user_comments_2.post_id 
    AND user_comments.id < user_comments_2.id  
where user_comments.post_id in (x,x,x) 
GROUP BY user_comments.id 
HAVING COUNT(*) < 3 
ORDER BY user_id, created_at 

(경고 포함) 나를 위해 @PaulSpiegel 한 작업에 의해 제안 된 대답을하지만 내가 사용하여 만든 솔루션을 결합 위로가는 종료 이 스레드에서이 정보 : link

Bill Karwin이 언급했습니다.

감사합니다. 대신 created_atid를 사용할 수있는 경우

+0

SELECT * FROM user_comments where user_id = 1 또는 user_id = 2 또는 user_id = 3 또는 user_id = 4 ORDER BY created_at DESC LIMIT 3; –

+0

AUTO_INCREMENT 열이 있습니까? –

+0

@PaulSpiegel - 예, id 열은 auto_inc입니다. – magnito

답변

2

, 당신은 사용자 당 최고 3 id으로 id을 비교할 수 있습니다. LIMIT 1 OFFSET 2으로 하위 쿼리에서 찾을 수 있습니다. 사용자의 의견이 3 개 미만인 경우 COALESCE (또는 IFNULL)를 사용하여 모든 의견을 id >= 0과 함께 선택하십시오.

SELECT * 
FROM user_comments c 
WHERE user_id IN (1, 2, 3, 4, 5) 
    AND id >= COALESCE((
    SELECT id 
    FROM user_comments c1 
    WHERE c1.user_id = c.user_id 
    ORDER BY id DESC 
    LIMIT 1 
    OFFSET 2 
), 0) 
ORDER BY user_id, id DESC 

당신이 주문에 대한 id을 사용할 수없는 경우 .. 3 및 4 댓글이 동일한 타임 스탬프가있는 경우는 다음 (가능성이 있지만), 3 개 이상의 의견을 얻을 수 있습니다

SELECT * 
FROM user_comments c 
WHERE user_id IN (1, 2, 3, 4, 5) 
    AND created_at >= COALESCE((
    SELECT created_at 
    FROM user_comments c1 
    WHERE c1.user_id = c.user_id 
    ORDER BY created_at DESC 
    LIMIT 1 
    OFFSET 2 
), '1970-01-01 00:00:00') 
ORDER BY user_id, created_at DESC 

주 .

+0

유감스럽게도 내 응용 프로그램에서는 초안으로 저장하고 나중에 게시 할 수 있기 때문에 주석 열에 의존 할 수 없습니다. – magnito

+0

@magnito 또한 타임 스탬프를 사용하여 작동하지만 메모를 읽습니다. 또한 하위 쿼리에 누락 된 ORDER BY 절을 추가했습니다. –

+0

BillKarwin이 언급 한 스레드에서 제안한 조인 솔루션을 사용하여이 작업을 거의 끝낼 수있었습니다. 그것은 중복 날짜와 동일한 문제가 없어 (내 상황에서) 더 빠릅니다. – magnito

1

select * 
from (
    select *, 
     @currentRank := if(@prevId = user_id, @currentRank, 0) + 1 as rank, 
     @prevId := user_id 
    from user_comments 
    order by user_id, created_at desc) as user_comments 
where rank <= 3 

내부 쿼리 행에서 값을 변경 SQL의 @ 변수을 행하기 위해 사용하십시오. 특정 사용자의 댓글은 order by user_id 때문에 함께 그룹화됩니다. @currentRank 변수는 특정 그룹의 행 순위를 저장합니다. 새로운 그룹이 시작될 때 @currentRank은 제로가됩니다.

user_comments 테이블의 각 레코드를 한 번만 반복하기 위해서는 RDMS가 필요하므로 결과가 최적으로 종료됩니다. 그러나 외부 where 절이 나중에 실행됩니다.