2013-06-01 4 views
0

아래의 SQL에는 일부 DDL과 간단한 쿼리가 포함되어 있습니다.SQL에서 많은 결과 제한 -

내가 얻고 그 결과는

a1|b1|c1 
a1|b2|c3 
a3|b3|c2 
a3|b3|c3 
a3|b3|c4 
a3|b3|c5 
a3|b5|c6 
a3|b5|c7 

내가 원하는 결과는 내가 MAX, MIN, rownums 무엇을하지를 사용하여 시도

a1 |b1 |c1 
a1 |b2 |c3 
a3 |b3 |c2 
null |null |c4 
null |null |c5 
a3 |b5 |c6 
null |null |c7 

입니다. 나는 지혜롭게 끝나고있다. 필자는 시작된 기본 쿼리 만 포함하고 있으며, 전혀 작동하지 않기 때문에 시도한 모든 옵션이 아닙니다. 어떤 도움을 주셔서 감사합니다!


BEGIN TRANSACTION; 

drop table if exists table_A; 
drop table if exists table_B; 
drop table if exists table_C; 

/* Create a table called NAMES */ 
CREATE TABLE table_A(a_Id text PRIMARY KEY, val_a text); 
CREATE TABLE table_B(a_Id text, b_Id text, val_b text); 
CREATE TABLE table_C(b_Id text, c_Id text, val_c text); 

/* Create few records in this table */ 
INSERT INTO table_A VALUES('a1','va1'); 
INSERT INTO table_A VALUES('a2','va2'); 
INSERT INTO table_A VALUES('a3','va3'); 

INSERT INTO table_B VALUES('a1', 'b1','vb1'); 
INSERT INTO table_B VALUES('a1', 'b2','vb2'); 
INSERT INTO table_B VALUES('a3', 'b3','vb31'); 
INSERT INTO table_B VALUES('a2', 'b4','vb4'); 
INSERT INTO table_B VALUES('a3', 'b5','vb31'); 

INSERT INTO table_C VALUES('b1', 'c1','vc1'); 
INSERT INTO table_C VALUES('b3', 'c2','vc2'); 
INSERT INTO table_C VALUES('b3', 'c3','vc3'); 
INSERT INTO table_C VALUES('b2', 'c3','vc3'); 
INSERT INTO table_C VALUES('b3', 'c4','vc2'); 
INSERT INTO table_C VALUES('b3', 'c5','vc3'); 
INSERT INTO table_C VALUES('b5', 'c6','vc3'); 
INSERT INTO table_C VALUES('b5', 'c7','vc3'); 

COMMIT; 

select 
a.a_Id, b.b_Id, c.c_Id 
from 
table_A as a 
join 
table_B as b 
on a.a_Id = b.a_Id 
join 
table_C as c 
on b.b_Id = c.b_Id; 
+1

샘플 당신은 매우 일반적이어서, 당신이 무엇을하고 있는지 말하기가 조금 어렵습니다. 성취 할 것.찾고있는 결과 세트가 있으면 조인이 작동하지 않는다고 말할 수 있습니다. 예를 들어 값 "c4"로 "table_C"를 가져옵니다. table_B에 참여하면 c의 b_id 열의 값이 b의 레코드와 일치하고 b의 레코드가 테이블 a의 값과 일치합니다. 따라서 where 절이 없으면 간단한 조인으로는 얻을 수 없다는 것을 제외하십시오. 이것이 많은 도움이되는지 확신 할 수 없지만 최종 목표가 무엇인지 판단하기가 어렵습니다. – AndrewK

+1

"oracle"이라는 질문에 태그를 추가했지만 게시 한 스크립트가 유효한 Oracle 구문이 아닙니다. 질문에 올바르게 태그를 추가 했습니까? –

+0

흠 .. 이런 식으로 보냅시다. 내 쿼리가 터플 자체 (key, value)를 던질 수 있습니다. 결과 집합에 값이 아직 선택되지 않은 튜플 만 포함되도록하고 싶습니다. 그래서 (k1, v1), (k2, v1), (k3, v2), (k4, v1)을 가질 수 있습니다. 내 쿼리에서 (k1, v1), (k2, null), (k3, v2), (k4, null) OR (k1, null), (k2, v1), (k3, v2) k4, null) 등등. 희망을 명확히 밝힙니다. – Neo

답변

1

뭔가 (너무 오라클에서 작동해야 내가 PostgreSQL을에 테스트 한) 작업을해야

SELECT 
    case when row_number = 1 then a_id end as a_id, 
    case when row_number = 1 then b_id end as b_id, 
    c_id 
FROM (
    SELECT 
    a.a_Id, 
    b.b_Id, 
    c.c_Id, 
    row_number() OVER (partition by a.a_id, b.b_id order by c.c_id) as row_number, --for a_id, b_id 
    row_number() OVER (partition by c.c_id order by c.c_id) as row_number2   --to avoid c_id duplicates 
    FROM 
    table_A a 
    join 
    table_B b on a.a_Id = b.a_Id 
    join table_C c on b.b_Id = c.b_Id 
) innerquery 
WHERE 
    row_number2 = 1 --this is to avoid c_id duplicates 

SQLFIDDLE

1

먼저 프리젠 테이션 논리에서 처리하는 것이 좋습니다. 그러나 SQL만으로도이를 수행 할 수 있습니다.

CASE과 함께 오라클의 LAG() 기능을 활용하여 이전 행의 id 값과 b 값이 동일한 지 확인할 수 있습니다.

다음은 공통 테이블 식 사용 예입니다 : 경우에 제발 내가 완전히 당신이 달성하려고하는 것을 이해 생각하지 않는다

with cte as (
    select 
    a.a_Id, b.b_Id, c.c_Id, 
    lag (a.a_Id,1) over (order by a.a_Id, b.b_Id) prev_a_Id, 
    lag (b.b_Id,1) over (order by a.a_Id, b.b_Id) prev_b_Id 
    from table_A a 
    join table_B b 
     on a.a_Id = b.a_Id 
    join table_C c 
     on b.b_Id = c.b_Id 
    order by 
    a.a_id, b.b_id 
) 
select 
    case 
     when prev_a_Id is null or 
      prev_a_Id <> a_Id or 
      prev_b_Id <> b_Id 
     then a_id 
    end new_a_Id, 
    case 
     when prev_a_Id is null or 
      prev_a_Id = a_Id or 
      prev_b_Id = b_Id 
     then b_id 
    end new_b_Id, c_Id 
from cte; 
0

을, 그러나 저를 정정 전 틀렸어.

처음에는 내부 조인을 사용하여 테이블을 조인합니다 (적어도 SQL Server를 사용하면되지만 오라클에서는 동일해야 함). 즉, 두 번째 테이블에 해당 행이있는 경우에만 첫 번째 테이블에서 행을 가져오고 두 번째 테이블에서 해당 행에 대해 첫 번째 테이블에 행이 있으면 두 번째 테이블의 행이 결과에 나타나지 않습니다.

달성하고자하는 결과에 대한 설명에 따르면 외부 조인은입니다. 정확히 왼쪽/오른쪽/전체 외부 조인 중 하나는 달성하기 위해 (외부 조인 또는 완전 외부 조인이 필요함) 나타납니다. 이 구체적인 예에서 데이터가 일반적인 경우가 아닌 것처럼 보이는 방식을 설명하기 때문에 정확한 목표가 확실하지 않습니다.

그래서 다른 결합 형태의 설명에 모양과 sql join types

또한 하나의 수입 발언을 선택하십시오 : 텍스트 유형은 아마 내가 1 차 키를 고려할 것 목록에서 마지막 유형입니다. 이 같은

+0

당신은 어딘가에 있습니다 ...이 질문은 내부 조인과 외부 조인의 차이점이 아닙니다. 하지만 추측 해 주셔서 감사합니다. – Hogan

+0

어쨌든 그 질문에 대한 대답에 투표하는 이유가 분명하지는 않습니다. –

+0

내가 왜 당신의 게시물을 downvoted 생각하십니까? – Hogan

1
select t1.a_id, t1.b_id, table_c.c_id 
from table_c 
left join 
(
    select a_Id, b_Id, c_Id 
    from 
    (
    select a.a_Id as a_id, b.b_Id as b_id, c.c_Id as c_id, 
      ROW_NUMBER() OVER (PARTITION BY a.a_ID, b.b_id ORDER BY C_ID) as aNum 
    from table_A as a 
    join table_B as b on a.a_Id = b.a_Id 
    join table_C as c on b.b_Id = c.b_Id 
) t2 
    where aNum = 1 
) t1 on table_c.c_id = t1.c_id 
order by table_c.c_id 

바이올린 :

http://sqlfiddle.com/#!3/6049b/1