Использование CASE и COUNT вместе в SQL-выражении - PullRequest
1 голос
/ 15 декабря 2011

Мне нужно написать оператор SQL, который может возвращать столбец с указанием трех вещей. Три вещи: «Действительный класс», «Несколько классов», «Не выбрано ни одного класса». Я использовал функцию, чтобы получить это для меня, но по мере роста записей в таблице этот метод несколько замедлился. Может кто-нибудь показать мне, как это можно сделать, не жертвуя скоростью, когда количество записей растет? Я думал, что какой-то случай может сосчитать вместе, но не могу понять.

Данные, которые мне нужно вернуть, будут выглядеть следующим образом.

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 ]

1 голос
/ 15 декабря 2011

Еще одна версия, очень похожая на предыдущие две;меньшее количество объединений, и не более одного класса будет просматриваться на одного учащегося (может иметь значение для действительно больших таблиц).

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 голосов
/ 15 декабря 2011

Я бы посмотрел на использование подзапроса, чтобы получить идентификатор студента и количество классов, затем снова нашел бы имя класса, когда есть только один, что-то вроде:

 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 голосов
/ 15 декабря 2011

Ваша схема должна выглядеть следующим образом

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...