2014-09-25 2 views
2

Я нашел аналогичный вопрос: What is the order of execution for this SQL statement. В принятом ответе указано, что FROM выполняется до любых других предложений.Порядок выполнения SQL при объединении двух таблиц и подсчете

SELECT StudentName, Students.StudentID, Cnt 
FROM (
    SELECT Students.StudentID, count(StudentCourses.CourselD) as [Cnt] 
    FROM Students LEFT JOIN StudentCourses 
    ON Students.StudentID = StudentCourses.StudentID GROUP BY Students.StudentID 
) T INNER JOIN Students on T.StudentID = Students.StudentID 

Как работает count() в этом случае?

Я смущен, потому что это, похоже, не соответствует моей логике. Предполагая, что LEFT JOIN во вложенном FROM выполняется сначала (пожалуйста, дайте мне знать, если это неверно). У нас будет по крайней мере одна строка для каждого учащегося как промежуточный вывод, возможно со значением null, если студент не проводит никаких курсов , Если для этого вывода применяется count(), у таких учеников будет 1 счет из-за нулевой стоимости, что не происходит в фактическом результате. Может ли кто-нибудь объяснить, как этот запрос выполняется под капотом?

Заранее благодарен

+0

Ваш вопрос точно? этот запрос работает нормально, потому что он действителен. кроме того, что вы делаете неверное предположение: вы не знаете порядок выполнения утверждений, поэтому не можете точно сказать, что операторы 'FROM' всегда выполняются первыми. ** логический порядок! = порядок выполнения ** – Paolo

+0

Я вижу, что запрос действителен, но я не уверен, как и когда применяется count(). Я сделал некоторые разъяснения в первоначальном вопросе, пожалуйста, дайте мне знать, если вы найдете мою формулировку запутанной. – Jas

ответ

0

Ваша проблема не в порядке выполнения. Я думаю, что это связано с тем, что

COUNT(StudentCourses.CourselD) 

будет считать только нулевые результаты.

Имея это как:

SELECT Students.StudentID, count(*) as [Cnt] 
FROM Students LEFT JOIN StudentCourses 
ON Students.StudentID = StudentCourses.StudentID GROUP BY Students.StudentID 

вернуть бы подсчет всех строк, а не только те, где курс ID не был пустым.

+0

Итак, эмпирическое правило: используйте count (*) для подсчета всех совпадающих строк и count (column), чтобы подсчитать их с помощью этого столбца! = Null? – Jas

0

COUNT() находится в подзапросе не во внешнем запросе. Вы выбираете только значение, возвращаемое count() во внешнем запросе.

Значение столбца Cnt в подзапросе будет целочисленным, большим или равным 0 (поскольку COUNT(NULL) возвращает 0, и не все учащиеся имеют строки в таблице StudentCourses, я считаю, что в этом столбце будут нули). Подзапрос возвращает одну строку для каждого ученика с COUNT() значением 0 или более.

Кроме того, как отметил Паоло в комментариях - логический порядок! = Порядок выполнения, поэтому не предполагайте, что выполнено до чего. У двигателей баз данных есть несколько механизмов для оптимизации выполнения запросов, поэтому вам следует предпочесть читать документы, предполагая, как что-то работает.

Смежные вопросы