2017-06-06 55 views
1

我想合併一些行。SQL合併Oracle中的行

首先,我的表和數據如下

GRP  CRRO_NO TYPE_CD TYPE_ID 
PERSON 1111  FATHER Tom 
PERSON 1111  MOTHER Jennifer 
PERSON 1111  JOB_  Teacher 
PERSON 1111  FRIEND Jimmy 
PERSON 1111  FRIEND Kim 
PERSON 1111  FRIEND Michael 

存在的,我希望得到像

GRP  CRRO_NO FATHER MOTHER  JOB_  FRIEND 
PERSON 1111  Tom  Jennifer Teacher Jimmy 
PERSON 1111  Tom  Jennifer Teacher Kim 
PERSON 1111  Tom  Jennifer Teacher Michael 

這種情況的結果是,如何寫SQL?

我一直喜歡

SELECT T1.GRP_CD GRP, T1.CRRO_NO CRRO 
     , MAX(T1.MOTHER) MOTHER, MAX(T1.FATHER) FATHER, MAX(T1.JOB_) JOB, T1.FRIEND FRIEND  
    FROM (
     SELECT DISTINCT 
       GRP_CD 
       ,CRRO_NO       
       ,CASE WHEN TYPE_CD = 'FATHER' THEN TYPE_ID ELSE '' END FATHER 
       ,CASE WHEN TYPE_CD = 'MOTHER' THEN TYPE_ID ELSE '' END MOTHER 
       ,CASE WHEN TYPE_CD = 'JOB_' THEN TYPE_ID ELSE '' END JOB_ 
       ,CASE WHEN TYPE_CD = 'FRIEND' THEN TYPE_ID ELSE '' END FRIEND 
     FROM TMP  
     WHERE 1=1 AND  TRIM(CRRO_NO) = '1111' 
     ) T1 
    WHERE T1.CRRO_NO = '1111' 
     GROUP BY T1.GRP_CD, T1.CRRO_NO, T1.FRIEND 
; 

然後,SQL的結果上面

GRP  CRRO_NO MOTHER  FATHER JOB  FRIEND 
PERSON 1111  Jennifer Tom  Teacher (null) 
PERSON 1111  (null)  (null) (null) Jimmy 
PERSON 1111  (null)  (null) (null) Kim 
PERSON 1111  (null)  (null) (null) Michael 

現在我知道爲什麼我的查詢的結果是錯誤的(不是我想要),但我仍然找不到方法。

其實,有嚴格的規定分類哪一個會被複制(母親,父親,作業),且不會(朋友)

由於種種原因,我不能修改的結構我表。 (我已經從我的商業條件改變了這個問題的內容,並簡化了情況說明)

請提供任何意見再次嘗試

+0

您是否嘗試過使用FRIEND列上的max將它從組中刪除? –

+0

@JorgeCampos是的,我已經嘗試過,但行數應該是三,因爲有三個朋友。 – kdragon

+0

然後你的解決方案將是你的實際查詢的內部連接,只需要像'select ...... where TYPE_CD ='FRIEND''這樣的朋友的子查詢,這個連接會給你3個結果......試試吧。 oooh並且不需要你的查詢中的'1 = 1'(我知道這可能來自一個懶惰程序員不希望檢查每個以前的條件= D的應用程序) –

回答

1

假設「母親」,「父親」和「JOB_」是唯一type_cd值,你可以實現你的目標,像這樣:

WITH sample_data AS (SELECT 'PERSON' grp, 1111 crro_no, 'FATHER' type_cd, 'Tom' type_id FROM dual UNION ALL 
        SELECT 'PERSON' grp, 1111 crro_no, 'MOTHER' type_cd, 'Jennifer' type_id FROM dual UNION ALL 
        SELECT 'PERSON' grp, 1111 crro_no, 'JOB_' type_cd, 'Teacher' type_id FROM dual UNION ALL 
        SELECT 'PERSON' grp, 1111 crro_no, 'FRIEND' type_cd, 'Jimmy' type_id FROM dual UNION ALL 
        SELECT 'PERSON' grp, 1111 crro_no, 'FRIEND' type_cd, 'Kim' type_id FROM dual UNION ALL 
        SELECT 'PERSON' grp, 1111 crro_no, 'FRIEND' type_cd, 'Michael' type_id FROM dual) 
-- end of mimicking a table called "sample_data" with your data in it. 
-- see the SQL below: 
SELECT grp, 
     crro_no, 
     father, 
     mother, 
     job_, 
     type_id friend 
FROM (SELECT grp, 
       crro_no, 
       type_cd, 
       type_id, 
       MAX(CASE WHEN type_cd = 'FATHER' THEN type_id END) OVER (PARTITION BY grp, crro_no) father, 
       MAX(CASE WHEN type_cd = 'MOTHER' THEN type_id END) OVER (PARTITION BY grp, crro_no) mother, 
       MAX(CASE WHEN type_cd = 'JOB_' THEN type_id END) OVER (PARTITION BY grp, crro_no) job_ 
     FROM sample_data) 
WHERE type_cd = 'FRIEND'; 

GRP  CRRO_NO FATHER MOTHER JOB_  FRIEND 
------ ---------- -------- -------- -------- -------- 
PERSON  1111 Tom  Jennifer Teacher Michael 
PERSON  1111 Tom  Jennifer Teacher Jimmy 
PERSON  1111 Tom  Jennifer Teacher Kim 

這是通過使用MAX()解析函數輸出的父親,母親和工作type_cd在所有行單獨列上TYPE_ID。

然後,只需過濾行以顯示type_cd ='FRIEND'行即可。

0

的自連接表就可以了:

select distinct t1.GRP, t1.CRRO_NO, t2.TYPE_ID as father, t3.TYPE_ID as mother, t4.TYPE_ID as JOB_, t5.TYPE_ID as FRIEND 
from TMP t1 
inner join TMP t2 on t2.CRRO_NO = t1.CRRO_NO 
        and t2.TYPE_CD = 'FATHER' 
inner join TMP t3 on t3.CRRO_NO = t1.CRRO_NO 
        and t3.TYPE_CD = 'MOTHER' 
inner join TMP t4 on t4.CRRO_NO = t1.CRRO_NO 
        and t4.TYPE_CD = 'JOB_' 
inner join TMP t5 on t5.CRRO_NO = t1.CRRO_NO 
        and t5.TYPE_CD = 'FRIEND'; 

但是請注意,因爲你不指定過濾謂詞(WHERE子句),在表TMP所有結果將被處理和你」會有重複的結果,因此使用「不同的」將是強制性的,當然如果您使用過濾器如:WHERE t1.type_cd = 'FATHER'

0

只能給出另一種方法來做到這一點。

with MFJQuery as (
select * from ( 
      select 
        A.GRP, 
        A.CRRO_NO, 
        A.TYPE_CD, 
        A.TYPE_ID 
      from test_data A 
      where A.TYPE_CD <> 'FRIEND') 
pivot 
(
    max(TYPE_ID) 
    for TYPE_CD in ('MOTHER' as "MOTHER", 
        'FATHER' as "FATHER", 
        'JOB_' as "JOB") 
)) 
select A.GRP, A.CRRO_NO, B.MOTHER, B.FATHER, B.JOB, A.TYPE_ID as FRIEND 
from test_data A inner join 
     MFJQuery B on A.GRP = B.GRP 
     and A.CRRO_NO = B.CRRO_NO 
where 
    A.TYPE_CD = 'FRIEND'