1

2 つのテーブルがあるとします。

table one:

| col1 |
- - - - -
| do   |
| big  |
| gone |

table two

| col1 | col2 | col3 | col4 |
- - - - - - - - - - - - - - -
| do   | blah | blah | big  |
| big  | do   | blah | gone |
| blah | blah | blah | blah |

table two表示される行に次のすべての値が含まれるようにcol1検索する方法table one

たとえば。与えられた状況の結果は

| col1 | col2 | col3 | col4 |
- - - - - - - - - - - - - - -
| big  | do   | blah | gone |
4

4 に答える 4

1

おそらく、これで最も難しい部分は、すべての列が 2 番目のテーブルに含まれていることを保証することです。それらを数えるだけでは十分ではなく、すべてがセットであることも確認する必要があります。

select t.*
from two t left outer join
     one o1
     on o1.col1 = t.col1 left outer join
     one o2
     on o2.col1 = t.col2 and o2.col1 not in (coalesce(t.col1, '')) left outer join
     one o3
     on o3.col1 = t.col3 and o3.col1 not in (coalesce(t.col1, ''), coalesce(t.col2, '')) left outer join
     one o4
     on o4.col1 = t.col4 and o4.col1 not in (coalesce(t.col1, ''), coalesce(t.col2, ''), coalesce(t.col3, '')) cross join
     (select count(*) as cnt from one) const
where const.cnt = ((case when o1.col1 is not null then 1 else 0 end) +
                   (case when o2.col1 is not null then 1 else 0 end) +
                   (case when o3.col1 is not null then 1 else 0 end) +
                   (case when o4.col1 is not null then 1 else 0 end)
                  )

oneこれは、値が以前に見られていないという条件付きで、テーブル内の各値を検索します。表に重複がある場合、oneそれらをどのように処理するかについて質問があります。それは、値が何度も表示されなければならないことを意味しますか?

于 2013-06-22T00:01:55.890 に答える
0

使用している SQL エンジンを指定しないでください。違いが生じる可能性があります。

row_number() 関数のサポートを必要とするソリューションを提供しました。少なくとも Oracle、DB2、SQLServer はすべて row_number() をサポートしていると思います。

テーブル 1 の個別の値が 1 つの行にピボットされると、問題はかなり単純になります。テーブル 1 に 4 つを超える個別の値が存在する場合、一致するものはありません。ピボットを行うためのより良い方法があるはずですが、この解決策が機能することはわかっています。

1つが空の場合、2つからすべての行が返され、1つに重複する行が無視されるように苦労しました。

with 
uniqueOne as ( 
  select distinct col1 from one 
),
ranked as (
  select col1, row_number() over (order by col1) seq from uniqueOne
),
vals as (
  select t1.col1 val1, 
         t2.col1 val2, 
         t3.col1 val3, 
         t4.col1 val4
    from (select 1 dummy) dummy
    left join ranked t1 on t1.seq=1
    left join ranked t2 on t2.seq=2
    left join ranked t3 on t3.seq=3
    left join ranked t4 on t4.seq=4
    left join ranked t5 on t5.seq=5
   where t5.seq is null
)
select two.*
  from two
 cross join vals
 where (vals.val1 is null or vals.val1 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val2 is null or vals.val2 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val3 is null or vals.val3 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val4 is null or vals.val4 in (two.col1, two.col2, two.col3, two.col4))
;


これがソリューションのライブデモです


私の良さ、私は自分の答えを読んで、もっと頻繁に調査を行うべきだと思います。SQLServer には、ソリューションを非常に効率的にするピボット演算子があります。Oracle にも Pivot がありますが、別の構文を使用します。

これは、SQLServer Pivot ソリューションの実際のデモです。甘い実行計画をご覧ください。

SQLServer クエリは次のとおりです。

with 
uniqueOne as ( 
  select distinct col1 from one 
),
ranked as (
  select col1, row_number() over (order by col1) seq from uniqueOne
),
vals as (
  select [1] val1, [2] val2, [3] val3, [4] val4, [5] val5
    from ranked
    pivot ( min(col1) for seq in ([1],[2],[3],[4],[5]) ) PivotTable
)
select two.*
  from two
  join vals on val5 is null
 where (vals.val1 is null or vals.val1 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val2 is null or vals.val2 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val3 is null or vals.val3 in (two.col1, two.col2, two.col3, two.col4))
   and (vals.val4 is null or vals.val4 in (two.col1, two.col2, two.col3, two.col4))
;
于 2013-06-22T01:41:32.160 に答える