2013-07-23 3 views
2

Я новичок в разработке SQL. Поэтому я хотел бы получить помощь от SO.SQL-запрос для получения данных

У меня есть три таблицы: студент, student_addresses, student_phones.

Их схема примерно следующим образом:

student 
------- 
student_id (Primary Key) 
student_name 
father_name 
mother_name 

student_addresses 
----------------- 
student_address_id (Primary Key) 
student_id (Foreign Key) 
address 
zip_code 

student_phones 
-------------- 
student_phone_id (Primary Key) 
student_id (Foreign Key) 
phone_type 
phone_number 

Оба student_addresses и student_phones является has_many отношения. Поэтому я хотел бы, чтобы выбрать все поля из студента для конкретного student_id но только подсчетов согласующих (всего) от student_addresses и student_phones для этого student_id. Как мне это получить?

Я попробовал этот запрос, но он возвращает ошибку:

SELECT students.student_id,student_name,father_name,mother_name, 
     COUNT(student_addresses.student_id) AS total_addresses,  
     COUNT(student_phones.student_id) AS total_phones 
FROM students,student_phones,student_addresses 
WHERE students.student_id = student_phones.student_id AND 
     students.student_id = student_addresses.student_id AND 
     students.student_id = 7; 

PS: В настоящее время я использую это на PostgreSQL. Тем не менее, я хотел бы также работать над MySQL. Значит ли это, что мне нужно иметь два разных запроса? AFAIK, для этой цели только один запрос будет работать на обоих (так как MySQL и PostgreSQL выполняют ту же самую реализацию SQL, насколько это требование запроса).

Мне интересно, если я могу сделать это, не используя GROUP BY. Потому что, предположим, что таблица студентов имеет больше полей, скажем, 12, тогда мне придется поместить все имена полей как в SELECT, так и в GROUP BY (AFAIK), что кажется немного неэлегантным.

+1

ли student_addresses и student_phones имеют свои первичные ключи? Если так, то кто они? Кроме того, вы используете PostgreSQL или MySQL? –

+0

@MarkBannister, я не заметил, что у него есть 2 разных БД. Я действительно думал, что это MySQL. Рад, что вы это указали. –

+0

@Mark: Я отредактировал вопрос. Благодарю. –

ответ

1

Это должно работать на MySQL и PostgreSQL:

SELECT s.student_id, 
     max(s.student_name) student_name, 
     max(s.father_name) father_name, 
     max(s.mother_name) mother_name, 
     COUNT(distinct a.student_address_id) total_addresses,  
     COUNT(distinct p.student_phone_id) total_phones 
FROM students s 
LEFT JOIN student_phones p ON s.student_id = p.student_id 
LEFT JOIN student_addresses a ON s.student_id = a.student_id 
WHERE s.student_id = 7 
GROUP BY s.student_id 
+2

Почему здесь требуется функция max()? –

+0

@ M-D: поскольку это сгруппированный запрос - все столбцы в предложении select должны быть либо включены в критерии группировки, либо агрегированы. Я предпочитаю использовать функцию агрегации (например, 'max'), потому что для полей, которые не являются ** обязательными ** для группировки, потому что более ясно, что такое« настоящая »группировка. –

+0

Отлично! Благодарю. –

1

Просто добавьте GROUP BY:

SELECT students.student_id,student_name,father_name,mother_name, 
     COUNT(student_addresses.student_id) AS total_addresses,  
     COUNT(student_phones.student_id) AS total_phones 
FROM students,student_phones,student_addresses 
WHERE students.student_id = student_phones.student_id AND 
     students.student_id = student_addresses.student_id AND 
     students.student_id = 7 
GROUP BY students.student_id,student_name,father_name,mother_name; 

Но если это случится, что студент с идентификатором-не имеет никакого адреса или нет номера телефона, он не будет возвращать никакого результата. Для того, чтобы вернуть то, что даже в этом случае, попробуйте использовать LEFT JOIN S:

SELECT students.student_id,student_name,father_name,mother_name, 
     COUNT(student_addresses.student_id) AS total_addresses,  
     COUNT(student_phones.student_id) AS total_phones 
FROM students 
LEFT JOIN student_phones ON students.student_id = student_phones.student_id 
LEFT JOIN student_addresses ON students.student_id = student_addresses.student_id 
WHERE students.student_id = 7 
GROUP BY students.student_id,student_name,father_name,mother_name; 
1

Вы забыли включить GROUP BY

SELECT students.student_id,student_name,father_name,mother_name, 
      COUNT(student_addresses.student_id) AS total_addresses,  
      COUNT(student_phones.student_id) AS total_phones 
    FROM students,student_phones,student_addresses 
    WHERE students.student_id = student_phones.student_id AND 
      students.student_id = student_addresses.student_id AND 
      students.student_id = 7 
    GROUP BY BY students.student_id,student_name,father_name,mother_name; 
+1

Мне интересно, если я могу это сделать без использования GROUP BY.Потому что, предположим, что таблица студентов имеет больше полей, скажем, 12, тогда мне придется поместить все имена полей как в SELECT, так и в GROUP BY, что кажется немного неэлегантным. Я не прав? –

+0

Можно просто создать 'VIEW' и сформировать другой запрос с помощью' INNER JOIN', но зачем беспокоиться, можете ли вы сделать это в одном запросе? –

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