2

次のようなスニペットを持つ表 Hobby があります。

Name    Activity    Hours

John    Hiking      .5
Sam     Cycling     .5
Sam     Swimming    1
Sam     Hiking      .5
John    Running     1
Sam     Sailing     1

(X, Y) のすべての人 X について、X と Y が共通していない活動時間の合計を見つけたいと思います。たとえば、John = X で Sam = Y の場合、John が持っていて Sam が持っていない唯一のアクティビティがランニングであるため、結果は 1 になります。

私のコードは次のとおりです。

select a.Name, b.Name, sum(a.Hours)
from Hobby a, Hobby b
where a.Name <> b.Name and a.Activity <> b.Activity
group by a.Name, b.Name;

しかし、これは私に間違った答えを与えました。コードの何が問題になっていますか?

4

4 に答える 4

4

これは難しい質問だと思います。私の最初のアプローチは、full outer join. しかし、ある名前で活動に一致するものがない場合、その名前も付けられないことに気付きました。

したがって、次のクエリは、名前のすべてのペアのリストを取得することによって機能します。これは順序付けられたリストであるため、指定された名前のペアは 1 回だけ表示されます。次に、これHobbyを使用してテーブルに 2 回結合しleft outer join、一致を取得します。ただし、重要なのは、一致がない場合Activityでも、その行が存在するが、NULL値があるということです。

このwhere句は、いずれかのテーブルActivityに があるすべての を検索しNULLます。これらは一致しないものです。次に、時間を合計するだけの簡単な問題です。

select names.Name1, names.Name2, sum(coalesce(h1.hours, h2.hours))
from (select distinct h1.Name as name1, h2.Name as name2
      from Hobby h1 cross join Hobby h2
      where h1.Name < h2.Name
     ) names left outer join
     Hobby h1
     on names.name1 = h1.name left outer join
     Hobby h2
     on names.name2 = h2.name and
        h1.Activity = h2.Activity
where h1.Activity is null or h2.Activity is null
group by names.Name1, names.Name2;
于 2013-09-19T22:06:20.993 に答える
0

あなたの from 句の読み取り

FROM Hobby a, Hobby b

from 句にコンマを入れると、最初のテーブルの各行が 2 番目のテーブルのすべての行と関連付けられることを意味する "CROSS JOIN" を意味します。where句を考えると、これはかなり大きな数になると思います。

クエリは少し異なる必要があります。

select sum(hours) 
from hobby 
where name = 'John' 
  and activity not in (
    select activity 
    from hobby 
    where name = 'Sam'
  )
于 2013-09-19T22:08:02.363 に答える