2016-11-09 62 views
3

表名稱中的字符串值,選擇屬性:複製如何基於一組

+------------------------------------+ 
| group_id | my_id | stuff  | 
+------------------------------------+ 

|  900 | 1  |  Y  | 
|  900 | 2  |  N  | 
|  901 | 3  |  Y  | 
|  901 | 4  |  Y  | 
|  902 | 5  |  N  | 
|  902 | 6  |  N  | 
|  903 | 7  |  N  | 
|  903 | 8  |  Y  | 
--------------------------------------- 

輸出應該是:

+------------------------------------+ 
| group_id | my_id | stuff  | 
+------------------------------------+ 
|  900 | 1  |  Y  | 
|  903 | 8  |  Y  | 
-------------------------------------- 

您好,我有一個表,我要辨別根據stuff字段中的正值(Y),group_id中的'good'記錄。如果只有一個值符合這個標準,我需要完整記錄。如果兩個東西的值都是Y或者都是N,那麼就不應該選擇它們。看起來這應該很簡單,但我不知道如何繼續。

+0

所以,輸入行總是成對出現,以及 「東西」 是NOT NULL? – mathguy

+0

道歉,有一些羣體> 2.如果一個記錄有東西是空的,其他東西='N',那麼都不應該返回。如果組中的所有記錄均爲空,則不應返回該組中的任何記錄。 – user7002207

+0

那麼如果Y有兩個,N有兩個,NULL是一個呢?或者一個與Y,兩個與N - 等?請不要以評論的方式回答;相反,編輯您的帖子並澄清要求。 – mathguy

回答

2

這裏的一個選擇是對每個group_id使用條件聚合,並保留一個組,如果它有一個yes和no的混合答案。該解決方案的

WITH cte AS (
    SELECT group_id 
    FROM Copies 
    GROUP BY group_id 
    HAVING SUM(CASE WHEN stuff = 'Y' THEN 1 ELSE 0 END) > 0 AND 
      SUM(CASE WHEN stuff = 'N' THEN 1 ELSE 0 END) > 0 
) 

SELECT c1.* 
FROM Copies c1 
INNER JOIN cte c2 
    ON c1.group_id = c2.group_id 
WHERE c1.stuff = 'Y' 

一個優點是,它會顯示的匹配記錄所有列。

+0

要求是選擇所有三列,而不僅僅是「group_id」。 – mathguy

+0

@mathguy我更新了我的答案。 –

+0

你好,我試圖運行這個,它給了我ORA-00933:SQL命令沒有正確結束。 – user7002207

0
with rows as(
select group_id, my_id, sum(case when stuff = 'Y' then 1 else 0 end) c 
    from copies 
    group by group_id, my_id) 
select c.* 
    from copies c inner join rows r on (c.group_id = r.group_id and c.my_id = r.my_id) 
    where r.c = 1; 
1
select group_id, 
     min(my_id) 
      keep (dense_rank first order by case stuff when 'Y' then 0 end) as my_id, 
     'Y' as stuff 
from table_1 
group by group_id 
having min(stuff) != max(stuff) 
+0

我怎麼能得到這個顯示錶中的所有屬性(除了這3個)? – user7002207

+0

同樣的方法 - 爲每個人添加'min(attribute_column)keep(dense_rank first case order by case stuff when'Y'then 0 end)as attribute_column'。由於每對只有一行使用「Y」,因此min()只在一行上,所以它只是值(「屬性」) - 但Oracle編譯器並不知道你知道,所以它確實需要'min()'(儘管你知道它不是必需的)。 – mathguy

+0

對不起,我可能錯了。有沒有辦法根據這個查詢做一個select *。在我的真實表格中,每個記錄有大約50個屬性。 – user7002207

0

試試這個:

SELECT t1.* 
FROM copies t1 
JOIN (
    SELECT group_id 
    FROM copies 
    GROUP BY group_id 
    HAVING COUNT(CASE WHEN stuff = 'Y' THEN 1 END) = 1 AND 
      COUNT(CASE WHEN stuff = 'N' THEN 1 END) = 1 
) t2 ON t1.group_id = t2.group_id 
WHERE t1.stuff = 'Y' 

這工作只要group_id值出現在夫婦。

+0

但是擴展查詢並不難,你只需要稍微調整'HAVING'子句。 –

+0

@TimBiegeleisen - 在任何情況下,都很難看出爲什麼這個問題需要基於連接的方法 - 尤其是那種也可以自己完成的聚合。 – mathguy

0

試試這個:

SELECT C.* 
FROM COPIES C, 
    COPIES C2 
WHERE C.STUFF='Y'  
AND C2.STUFF='N' 
AND C.GROUP_ID=C2.GROUP_ID