2009-12-27 2 views
0

Вот две таблицы в отношениях родителя/ребенка. Что мне нужно сделать, это выбрать студентов там средний балл:как я могу переписать запрос выбора в этой ситуации

CREATE TABLE dbo.Students(
Id int NOT NULL, 
Name varchar(15) NOT NULL, 
CONSTRAINT PK_Students PRIMARY KEY CLUSTERED 
(

CREATE TABLE [dbo].[Results](
Id int NOT NULL, 
Subject varchar(15) NOT NULL, 
Mark int NOT NULL 
) 

ALTER TABLE [dbo].[Results] WITH CHECK ADD CONSTRAINT [FK_Results_Students] FOREIGN KEY([Id]) 
REFERENCES [dbo].[Students] ([Id]) 

Я написал запрос, как это:

SELECT name , coalesce(avg(r.[mark]),0) as Avmark 
FROM students s 
LEFT JOIN results r ON s.[id]=r.[id] 
GROUP BY s.[name] 
ORDER BY ISNULL(AVG(r.[mark]),0) DESC; 

Но результат является то, что все студенты с там они среднюю отметку в алфавиту order.What мне нужно ограничить набор результатов со студентами, которые имеют самую высокую среднюю оценку, чем другие, т. е. если у двух учеников есть знак avg 50 и 1 с 25, мне нужно отображать только тех студентов с 50. Если есть только один студент с наивысшей отметкой avg - только он должен появиться в наборе результатов. Как я могу сделать это наилучшим образом?

+0

Какая версия SQL Server? –

ответ

-1
SELECT name as 'ФИО', 
coalesce(avg(r.[mark]),0) as 'Средний бал' 
FROM students s 
LEFT JOIN results r 
ON s.[id]=r.[id] 
GROUP BY s.[name] 
HAVING AVG(r.[mark]) >= 50 
ORDER BY ISNULL(AVG(r.[mark]),0) DESC 

about HAVING clause

+0

-1 Это не отвечает на вопрос. Пользователь не запрашивал список студентов с отметкой выше 50. Пользователю нужны пользователи с наивысшей отметкой - независимо от того, какой знак. –

0

Если вы используете относительно новую версию сервера MS SQL, вы можете использовать WITH, чтобы сделать это просто написать:

WITH T AS (
    SELECT 
     name, 
     coalesce(avg(r.[mark]),0) as mark 
    FROM students s 
    LEFT JOIN results r ON s.[id]=r.[id] 
    GROUP BY s.[name]) 
SELECT name as 'ФИО', mark as 'Средний бал' 
FROM T 
WHERE T.mark = (SELECT MAX(mark) from T) 
1

SQL Server 2005+, используя , CTE:

WITH grade_average AS (
    SELECT r.id, 
      AVG(r.mark) 'avg_mark' 
    FROM RESULTS r 
GROUP BY r.id), 
    highest_average AS (
    SELECT MAX(ga.avg_mark) 'highest_avg_mark' 
    FROM grade_average ga) 
SELECT DISTINCT 
     s.name, 
     ga.avg_mark 
    FROM STUDENTS s 
    JOIN grade_average ga ON ha.id = s.id 
    JOIN highest_average ha ON ha.highest_avg_mark = ga.avg_mark 

Non-CTE эквивалент:

SELECT DISTINCT 
     s.name, 
     ga.avg_mark 
    FROM STUDENTS s 
    JOIN (SELECT r.id, 
       AVG(r.mark) 'avg_mark' 
      FROM RESULTS r 
     GROUP BY r.id) ga ON ha.id = s.id 
    JOIN SELECT MAX(ga.avg_mark) 'highest_avg_mark' 
     FROM (SELECT r.id, 
         AVG(r.mark) 'avg_mark' 
       FROM RESULTS r 
      GROUP BY r.id) ga) ha ON ha.highest_avg_mark = ga.avg_mark 
0

Это просто? Для всех версий SQL Server 2000+

SELECT TOP 1 WITH TIES 
    name, ISNULL(avg(r.[mark]),0) as AvMark 
FROM 
    students s 
    LEFT JOIN 
    results r ON s.[id]=r.[id] 
GROUP BY 
    s.[name] 
ORDER BY 
    ISNULL(avg(r.[mark]),0) DESC; 
Смежные вопросы