2012-12-01 2 views
0

두 개의 테이블, 상태 및 항목이 있습니다. 하위 하위 선택 및 그룹화 : 그룹의 최대 값을 포함하는 행에서 이름 열 가져 오기

States

:

+----+------+-------+----------+ 
| id | name | state | priority | 
+----+------+-------+----------+ 
| 1 | AA | 10 |  1 | 
| 2 | AB | 10 |  2 | 
| 3 | AC | 10 |  3 | 
| 4 | BA | 20 |  1 | 
| 5 | BB | 20 |  5 | 
| 6 | BC | 20 |  10 | 
| 7 | BD | 20 |  50 | 
+----+------+-------+----------+ 

Items :

+----+--------+-------+ 
| id | item | state | 
+----+--------+-------+ 
| 1 | Blue | 10 | 
| 2 | Red | 20 | 
| 3 | Green | 20 | 
| 4 | Yellow | 10 | 
| 5 | Brown | 10 | 
+----+--------+-------+ 

priority 열은 Items 표에 사용되지 않지만 다음과 같이 원하는 데이터를 점점 복잡하게한다.

는 내가 원하는 것은 가장 높은 우선 순위statename 각 행의 state.id 값을 대체하는 Items 테이블의 행의 목록입니다.

결과는 같을 것이다 :

+----+--------+-------+ 
| id | item | state | 
+----+--------+-------+ 
| 1 | Blue | AC | 
| 2 | Red | BD | 
| 3 | Green | BD | 
| 4 | Yellow | AC | 
| 5 | Brown | AC | 
+----+--------+-------+ 

는 여기에 내가 함께 왔어요 작은 괴물. 이것이 최선의 방법입니까, 아니면 더 효율적입니까/덜 장황 할 수 있습니까? (하위 하위 선택 내 손바닥 가려움을 - P.)

SELECT * 
FROM 
    Items AS itm 
    INNER JOIN (SELECT sta.name, sta.state 
       FROM (SELECT state, MAX(priority) [highest] 
        FROM States 
        GROUP BY state) AS pri 
       INNER JOIN States AS sta 
        ON sta.state = pri.state 
        AND sta.priority = pri.highest) AS nam 
    ON item.state = name.state 

업데이트 : 나는

+1

'Item.state'는 예제 데이터의 'stetes.id'에 대한 외래 키가 아닙니다. – Laurence

+0

@Laurence : 잘 잡으세요. 업데이트 됨. 감사! – Lemur

답변

1

당신은 버전을 게시되지 않은 MS-SQL 2005과 MS-SQL 2008R2를 사용하고 있습니다 SQL 서버.

CREATE TABLE dbo.States(id INT, name NVARCHAR(25), state INT, priority INT); 
INSERT INTO dbo.States 
VALUES 
( 1 ,'AA', 10 ,  1), 
( 2 ,'AB', 10 ,  2), 
( 3 ,'AC', 10 ,  3), 
( 4 ,'BA', 20 ,  1), 
( 5 ,'BB', 20 ,  5), 
( 6 ,'BC', 20 ,  10), 
( 7 ,'BD', 20 ,  50); 

CREATE TABLE dbo.Items(id INT ,item NVARCHAR(25), state INT); 
INSERT INTO dbo.Items 
VALUES 
( 1 ,'Blue', 10), 
( 2 ,'Red', 20), 
( 3 ,'Green', 20), 
( 4 ,'Yellow', 10), 
( 5 ,'Brown', 10); 


SELECT i.id, 
     i.item, 
     s.name, 
     s.priority 
FROM dbo.Items i 
CROSS APPLY (
SELECT *,ROW_NUMBER()OVER(ORDER BY priority DESC) rn FROM dbo.States si WHERE si.state = i.state 
)s 
WHERE s.rn = 1; 

크로스 조인과 같은 작품을 적용하지만, 오른쪽에서 왼쪽에있는 열을 참조 할 수 있습니다 : 2005에있는 이상이 같은 적용 십자가와 함께 ROW_NUMBER() 함수를 사용할 수 있습니다 가정 where 절에서 볼 수 있듯이. ROW_NUMBER() 함수는 우선 순위가 가장 높은 행이 항상 1을 갖도록 역순 우선 순위로 현재 상태 값과 일치하는 상태 테이블의 모든 행에 번호를 매 깁니다. 마지막 where 절은 해당 행만 필터링합니다. A Join A Day
십자가는 8 일 (2012년 12월 8일)의 주제가 될 것입니다 적용 :

는 편집 : 조인에 대해

난 그냥 블로그 시리즈를 시작했다.

+0

우수. 이게 내가 원하는거야. CROSS APPLY를 본 것은 처음입니다. 고맙습니다! – Lemur

관련 문제