2017-02-20 3 views
0

がテーブルを考える:私は言い換えれば結果にSQLを使用してグループの出現を数え、2つの異なる列をソートされていないセットとして扱う方法は?

green,red: 3 
blue,red: 1 

を取得したいと思い

CREATE TABLE foo (
    thing_a VARCHAR2(15), 
    thing_b VARCHAR2(15) 
); 

と行

INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green'; 
INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green'; 
INSERT INTO foo (thing_a, thing_b) VALUES 'green', 'red'; 
INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'blue'; 

を、私はそれぞれの発生をカウントしたいですthing_aとthing_bのグループですが、私は "赤"と "緑"を "緑"と "赤"と同じにしたいと考えています。

私は「解決策」に来て最も近いがこれです:

greenred 
bluered 

だから、それは正確にグループ分けが、それは何もカウントされませんん生み出す

SELECT DISTINCT (
    CASE WHEN thing_a < thing_b 
    THEN thing_a || thing_b 
    ELSE thing_b || thing_a END 
) as thing FROM foo; 

これを解決する方法の提案はありますか?

答えて

0

あなたは近くにあります。単に派生テーブルにcaseクエリをラップして、GROUP BYその結果:

select thing, count(*) 
from 
(
    SELECT CASE WHEN thing_a < thing_b THEN thing_a || thing_b 
      ELSE thing_b || thing_a 
      END as thing 
    FROM foo 
) dt 
group by thing 

すぎるABとCDEなどの無項目を確認してくださいとABCDと電子と混同させるには、列の間にカンマを追加します。 (これを指摘するためにmathguyのおかげ!)また

select thing, count(*) 
from 
(
    SELECT CASE WHEN thing_a < thing_b THEN thing_a || ', ' || thing_b 
      ELSE thing_b || ', ' || thing_a 
      END as thing 
    FROM foo 
) dt 
group by thing 

、派生テーブルでUNION ALLを行い、そしてGROUP BYその結果:

select ta, tb, count(*) 
from 
(
    select thing_a as ta, thing_b as tb from foo where thing_a <= thing_b 
    union all 
    select thing_b, thing_a from foo where thing_a > thing_b 
) dt 
group by ta, tb 

ANSI SQLに準拠し、ポータブル!

+0

@AugustLilleaas - この回答に「正しい」と表示されていますが、これはあなたの経験を考慮すると驚くべきものです。データに '( 'ab'、 'cde')'と '( 'abcd'、 'e')という順序のないセットがあるとします。このソリューションは、同じものとして扱います。 – mathguy

+0

@mathguy、oops ...私は何と言うことができますか?aとbの間にカンマを追加するのは簡単な編集のようです。 1分後に確認してください。 – jarlh

+0

文字列自体にコンマが含まれていると、これは機能しません。 – mathguy

1

これはすべて単一のSELECTステートメントで行うことができます。最小値、最大値でグループ化します。注:どちらの列にもnullがある場合、これは機能しません。可能性がある場合は、それを処理するために少し注意を払ってクエリを記述する必要があります。

with 
    foo (thing_a, thing_b) as (
     select 'red' , 'green' from dual union all 
     select 'red' , 'green' from dual union all 
     select 'green', 'red' from dual union all 
     select 'red' , 'blue' from dual union all 
     select 'ab' , 'cde' from dual union all 
     select 'abcd' , 'e'  from dual union all 
     select 'cde' , 'ab' from dual 
    ) 
-- end of test data; SQL query begins BELOW THIS LINE 
select least(thing_a, thing_b) as thing_a, greatest(thing_a, thing_b) as thing_b, 
     count(*) as cnt 
from foo 
group by least(thing_a, thing_b), greatest(thing_a, thing_b) 
order by thing_a, thing_b -- if needed 
; 

THING_A THING_B CNT 
------- ------- --- 
ab  cde  2 
abcd e   1 
blue red  1 
green red  3 

4 rows selected. 
+0

それは非常に興味深いです、私はあなたがグループで機能を使うことができるのか分かりませんでした!私は自分のデータにnullがないので、これはうまくいくでしょう。 –

関連する問題