2011-12-15 3 views
1

3つのことを示す列を返すSQL文を記述する必要があります。 3つのものは、「実際のクラス」、「複数のクラス」、「選択されたクラスがない」です。私はこれを得るために関数を使用しましたが、テーブルレコードが大きくなるにつれて、このメソッドはかなり遅くなりました。レコードの量が増えたときにスピードを犠牲にすることなく、これをどうやって行うことができるかを誰かに教えてもらえますか?私はいくつかのタイプの症例が一緒に数えられると思っていましたが、それを理解することはできません。SQL文でCASEとCOUNTを併用する

返されるデータは次のようになります。

 
Student   Classes 
Bugs Bunny  Multiple Classes 
Daffy Duck  Biology 101 
Porky Pig  No Classes Selected 
 
Schema 

Student 
StudentId int 
Name 

Class 
ClassId int 
Name 

StudentClass 
StudentId 
ClassId 
+3

あなたが含まれるように質問を編集しませんでしたあなたが提供した出力に対応するスキーマ/ベースデータ? –

+2

あなたはすでに使用している機能を投稿できますか?(テーブル構造を理解していなくてもすべては少し仮説です) –

+0

スキーマを忘れると残念です。私のスキーマは最初の回答に掲載されたものと同じです。 –

答えて

1

もう1つのバージョンは、前の2つのバージョンとよく似ています。結合数は少なくなりますが、1クラスにつき1つのクラスが検索されます(本当に大きなテーブルで違いが生じるかもしれません)。

SELECT 
    xx.Name 
    ,case xx.ClassCount 
    when 0 then 'No Classes Selected' 
    when 1 then cl.Name 
    else 'Multiple Classes' 
    end Classes 
from (-- Count classes per student 
     select 
      st.Name 
     ,count(sc.ClassId) ClassCount 
     ,max(sc.ClassId) OneClass -- If a student has one class, this is it 
     from Students st 
     left outer join StudentClass sc 
      on sc.StudentId = st.StudentId 
     group by st.Name) xx 
    left outer join Classes cl 
    on cl.ClassId = xx.OneClass 

(、デバッグすることはできませんうまくいけばなしタイプミス...)

(デバッグ、うまくいけば何よりタイプミス...することはできません)

+0

私はちょうど仕事の上に右を得ていたが、私はこれが私のアプリのこの分野では本当の大きな可能性があるので、これをチェックします。ありがとう。 –

+0

最後の行には、xx.ClassIdがあります。そのため、「無効な列名」が発生します。次に、最初のFROMの後にSELECTに 'sc.ClassId'を追加して、エラーを取り除きます。それから私はそれを実行すると、それは集計関数またはGROUP BY句に含まれていないので、選択リストに無効です。それを間違って修正しようとしましたか? –

+0

私はそれを誤ってコード化し、それを編集します。サブクエリ内のシングルトンClassIdに割り当てられたエイリアスであるため、 "xx.ClassId"は "xx.OneClass"である必要があります。 (それで、私は自分自身を実行することができないコードサンプルの終わりに「デバッグできません」という免責事項を入れています...) –

0

あなたのスキーマがこの

Student 
StudentId int 
Name 

Class 
ClassId int 
Name 

StudentClass 
StudentId 
ClassId 

のようになります。そして、あなたのクエリは次のようになります。

select 
    s.Name, 
    CASE x.ClassCount when 0 then 'No Classes Selected' when 1 then c.Name else 'Multiple Classes' 
from 
    Student s 
    inner join 
(select 
    StudentId, count(sc.ClassId) as ClassCount 
from 
    Student s 
    left outer join StudentClass sc on s.StudentId = sc.StudentId 
group by 
    s.StudentId) x on s.StudentId = x.StudentId 
    left outer join StudentClass sc2 on sc2.StudentId = x.StudentId and x.ClassCount = 1 
    left outer join Class c on c.ClassId = sc2.ClassId 
+0

スキーマを追加しないと申し訳ありませんが、表示されたものはまさに私が持っているものです。残念ながら、私は '無効な列名ClassCount'を取得します。 –

+0

理由がわかりません。 ClassCountの名前を付ける前に「as」という単語を追加しましたが、それは問題ではありません。再度試してみる価値がある。 – jmacinnes

0

私は学生証を取得するには、サブクエリを使用して見てしまうと、クラスカウントは、1つしかない場合はクラス名を再度検索します。

Select s.Name, 
    Case s.Count 
     When 0 Then 'No Classes Selected' 
     When 1 Then c.className 
     Else 'Multiple Classes' 
    End 
From (
    select s.id, s.name, count(cs.id) as Count 
    From student s 
    left join studentclass cs on c.studentid = s.id 
    group by s.id, s.name 
) as s 
left join studentclass cs on c.studentid = s.id 
left join class c on c.id = cs.classid 

もちろん、古い学校では、サブクエリを共通テーブル式(CTE)に分解することができます。

+0

名前でのみグループ化しているのと同じステートメントでClassIdを選択できないため、これは機能しません。 – jmacinnes

+0

かなり正しい.....更新 –