2010-07-18 4 views
3

저는 Sql-Server 2005를 사용하고 있습니다.params에서 top x를 선택하는 방법은 무엇입니까?

사용자 ID와 성별을 가진 Users 테이블이 있습니다. userID desc로 상위 1000 명의 남성 (0)과 상위 1000 명의 여성 (1)을 선택하고 싶습니다.

내가 공용체를 생성하면 하나의 결과 집합 만 userID desc에 의해 정렬됩니다. 다른 방법은 무엇입니까?

SELECT top 1000 * 
FROM Users 
where gender=0 
union 
SELECT top 1000 * 
FROM Users 
where gender=1 
order by userID desc 
+0

당신이 당신의 쿼리의 SQL을 게시 할 수 일을하는 또 다른 방법? 특히 괄호와 위치 또는 'order by'절과 같은 것에 대해 궁금합니다. – sje397

+0

@ sje397, 나중에 완료 – eugeneK

+0

어떤 기준으로 상위 1000 개를 고르려고하십니까? 현재 조합 위에있는 쿼리는 무작위로 효과적으로 선택됩니다. –

답변

3

WITH TopUsers AS 
(
SELECT UserId, 
     Gender, 
     ROW_NUMBER() OVER (PARTITION BY Gender ORDER BY UserId DESC) AS RN 
    FROM Users 
    WHERE Gender IN (0,1) /*I guess this line might well not be needed*/ 
) 

SELECT UserId, Gender 
FROM TopUsers 
WHERE RN <= 1000 
ORDER BY UserId DESC 
+0

내 것보다 훨씬 더 우아한 해결책. 더 나은 수행합니다. 나는 그것을 기억할 것이다. 감사. –

+0

내가 너없이 무엇을 할 것인가, 마틴 스미스? 나는 너에게서 응답의 90 %로 끝난다! – eugeneK

0

조합에 대한 하위 선택을 작성한 다음 조합 결과에 대해 순서를 지정해야합니다.

이런 식으로 뭔가 작업을해야합니다 :

SELECT u.* 
    FROM (SELECT u1a.* FROM (SELECT TOP 1000 u1.* 
          FROM USERS u1 
          WHERE u1.gender = 0 
          ORDER BY u1.userid DESC) u1a 
     UNION ALL 
     SELECT u2a.* FROM (SELECT TOP 1000 u2.* 
          FROM USERS u2 
          WHERE u2.gender = 1 
          ORDER BY u2.userid DESC) u2a 
     ) u 
ORDER BY u.userid DESC 

을 또한, 모든 나은 성능을 제공하는 UNION을 사용하여 DB를 중복 검사 귀찮게하지 않으므로 (이이 쿼리에 없을 것)에의 결과.

+0

어쩌면 틀 렸지만 어쩌면 어떤 요인에 따라 최고 남성과 여성을 선택할 것입니까? – eugeneK

+0

닫기하지만 작동하지 않을 경우 남성 인 1000 명과 여성 인 1000 명을 선택합니다. 최신 1000을 원합니다. –

+0

빠른 입력을 통한 오류 - 이제 수정되었습니다. – Tom

1

일부 테스트를 완료하면 결과가 이상합니다. 에 의해 순서는 노조의 끝에서해야하기 때문에, 의미가

select top 2 * from @users where gender = 0 order by id 
union all 
select top 2 * from @users where gender = 1 order by id 

: 당신이 노동 조합의 두 부분에 order by을 지정하는 경우, SQL Server는 구문 오류가 있습니다. 그러나 하위 쿼리에서 동일한 구문을 사용하면 컴파일됩니다! 당신이 하위 쿼리 조합에 대해 하나의 order by을 지정할 때

select * from (
    select top 2 * from @users where gender = 0 order by id 
    union all 
    select top 2 * from @users where gender = 1 order by id 
) sub 

이상한 일이 발생합니다 : 그리고 예상대로 작동

select * from (
    select top 2 * from @users where gender = 0 
    union all 
    select top 2 * from @users where gender = 1 order by id 
) sub 

가 지금은 무작위로 노조의 전반을 주문하지만, 하반기 이드. 그것은 꽤 예기치 않습니다. 같은 일이 상반기에 order by으로 발생합니다

select * from (
    select top 2 * from @users where gender = 0 order by id desc 
    union all 
    select top 2 * from @users where gender = 1 
) sub 

나는이 구문 오류를주고 기대하지만, 대신 노조의 전반을 주문한다. 따라서 union이 서브 쿼리의 일부일 때 다른 방법으로 order by과 상호 작용하는 것처럼 보입니다.

select * 
from (
     select * 
     from (
       select top 2 * 
       from @users 
       where gender = 0 
       order by 
         id desc 
       ) males 
     union all 
     select * 
     from (
       select top 2 * 
       from @users 
       where gender = 1 
       order by 
         id desc 
       ) females 
     ) males_and_females 
order by 
     id 

예 데이터 :

declare @users table (id int identity, name varchar(50), gender bit) 

insert into @users (name, gender) 
      select 'Joe', 0 
union all select 'Alex', 0 
union all select 'Fred', 0 
union all select 'Catherine', 1 
union all select 'Diana', 1 
union all select 'Esther', 1 
크리스 다이버처럼

는 원래 명시 적으로 모든 노동 조합에 order by에 의존하고, 지정하지 않는 것입니다, 혼란에서 얻을 수있는 좋은 방법을 게시
+0

Tom과 같은 실수입니다 –

+0

왜 이중 하위 쿼리가 필요합니까? 내 쿼리가 작동하지 않습니다. –

+0

@Chris Diver : 쿼리가 작동합니다. 나는 최종 주문서가 적용되는 내용을 더욱 분명히 쓰고 있습니다. – Andomar

3

Martin Smith의 솔루션이 다음보다 낫습니다.

SELECT UserID, Gender 
FROM 
    (SELECT TOP 1000 UserId, Gender 
    FROM Users 
    WHERE gender = 0 
    ORDER BY UserId DESC) m 
UNION ALL 
SELECT UserID, Gender 
FROM 
(SELECT TOP 1000 UserId, Gender 
    FROM Users 
    WHERE gender = 1 
    ORDER BY UserId DESC) f 
ORDER BY Gender, UserID DESC 

이 당신이 원하는, 당신이 오히려 먼저 최신 사용자가 원하는 경우에 의해 순서를 변경 않지만, 그것은 당신에게 각각의 상단 1000을 얻을 것이다.

+0

+1 맞습니다. 주문에 집중하고 성별로 상위 1000 원을 놓친 것 같습니다. – Andomar

+0

닫기, 성별로 주문하는 경우 그때 당신은 다시 떨어져 남성과 여성을 분할. – Tom

+0

@Chris Diver, 네가 맞다. 그냥 어쩌면 거기에 조금 더 빠른 솔루션이 있습니다 ... – eugeneK

관련 문제