0

Использование результата SELECT в другом SELECT

14

Проблема с SQL-запросом для получения средней оценки за последние 3 месяца

Я пытаюсь создать SQL-запрос, который возвращает результаты для таблицы лидеров в формате GridView. Моя цель — получить среднее значение оценок, которые были выставлены за последние 3 месяца.

Вот мой первоначальный запрос:

SELECT 
    * 
FROM 
    Score AS NewScores 
WHERE 
    InsertedDate >= DATEADD(mm, -3, GETDATE());

SELECT 
    ROW_NUMBER() OVER( ORDER BY NETT) AS Rank, 
    Name, 
    FlagImg, 
    Nett, 
    Rounds 
FROM (
    SELECT 
        Members.FirstName + ' ' + Members.LastName AS Name, 
        CASE 
            WHEN MenuCountry.ImgURL IS NULL THEN 
                '~/images/flags/ismygolf.png' 
            ELSE 
                MenuCountry.ImgURL 
        END AS FlagImg, 
        AVG(CAST(NewScores.NetScore AS DECIMAL(18, 4))) AS Nett, 
        COUNT(Score.ScoreID) AS Rounds 
    FROM 
        Members 
        INNER JOIN 
        Score 
            ON Members.MemberID = Score.MemberID 
        LEFT OUTER JOIN MenuCountry 
            ON Members.Country = MenuCountry.ID 
    WHERE 
        Members.Status = 1 
    GROUP BY 
        Members.FirstName + ' ' + Members.LastName, 
        MenuCountry.ImgURL
    ) AS Dertbl 
ORDER BY;

Однако при выполнении этого запроса возникает ошибка:

Msg 4104, Level 16, State 1, Line 2
The multi-part identifier "NewScores.NetScore" could not be bound.

Эта ошибка возникает из-за строчки:

AVG(CAST(NewScores.NetScore AS DECIMAL(18, 4))) AS Nett

Мне нужно использовать NewScores, чтобы я мог получать только среднее значений оценок за последние 3 месяца.

Вопрос:

Как мне изменить запрос, чтобы я мог использовать NewScores и получить среднее значение оценок только тех, которые были выставлены меньше 3 месяцев назад?


Редактирование:

Используя предоставленные ответы, я успешно решил проблему, добавив необходимое соединение в правильном месте. Вот исправленный запрос:

SELECT 
    ROW_NUMBER() OVER(ORDER BY NETT) AS Rank, 
    Name, 
    FlagImg, 
    Nett, 
    Rounds 
FROM (
    SELECT 
        Members.FirstName + ' ' + Members.LastName AS Name, 
        CASE 
            WHEN MenuCountry.ImgURL IS NULL THEN 
                '~/images/flags/ismygolf.png' 
            ELSE 
                MenuCountry.ImgURL 
        END AS FlagImg, 
        AVG(CAST(NewScores.NetScore AS DECIMAL(18, 4))) AS Nett, 
        COUNT(NewScores.ScoreID) AS Rounds 
    FROM 
        Members 
        INNER JOIN (
            SELECT * 
            FROM Score 
            WHERE InsertedDate >= DATEADD(mm, -3, GETDATE())
        ) AS NewScores 
            ON Members.MemberID = NewScores.MemberID 
        LEFT OUTER JOIN MenuCountry 
            ON Members.Country = MenuCountry.ID 
    WHERE 
        Members.Status = 1 
    GROUP BY 
        Members.FirstName + ' ' + Members.LastName, 
        MenuCountry.ImgURL
) AS Dertbl 
ORDER BY Nett ASC;

Теперь запрос работает корректно.

3 ответ(ов)

0

Ваш запрос можно объединить для улучшения читаемости и производительности. Попробуйте следующий вариант:

SELECT 
    ROW_NUMBER() OVER (ORDER BY Nett) AS Rank, 
    Name, 
    FlagImg, 
    Nett, 
    Rounds 
FROM (
    SELECT 
        Members.FirstName + ' ' + Members.LastName AS Name, 
        COALESCE(MenuCountry.ImgURL, '~/images/flags/ismygolf.png') AS FlagImg, 
        AVG(CAST(NewScores.NetScore AS DECIMAL(18, 4))) AS Nett, 
        COUNT(NewScores.ScoreID) AS Rounds 
    FROM 
        Members 
    INNER JOIN 
        Score NewScores ON Members.MemberID = NewScores.MemberID 
    LEFT JOIN 
        MenuCountry ON Members.Country = MenuCountry.ID 
    WHERE 
        Members.Status = 1 
        AND NewScores.InsertedDate >= DATEADD(month, -3, GETDATE())
    GROUP BY 
        Members.FirstName + ' ' + Members.LastName, 
        MenuCountry.ImgURL
) AS Dertbl 
ORDER BY Nett;

В этом запросе я использовал функцию COALESCE, чтобы упростить обработку значений NULL для флага страны. Также исправил часть с чтением поля ScoreID в COUNT, чтобы избежать путаницы. Пожалуйста, убедитесь, что имена таблиц и столбцов корректны и соответствуют вашей схеме базы данных.

0

Что вам нужно, так это запрос с использованием конструкции WITH, если ваша СУБД это поддерживает. Тогда ваш запрос будет выглядеть так:

WITH NewScores AS (
    SELECT * 
    FROM Score  
    WHERE InsertedDate >= DATEADD(mm, -3, GETDATE())
)
SELECT 
<и остальная часть вашего запроса>

Обратите внимание, что в первой части нет ;. Надеюсь, это поможет!

0

Вы пропустили таблицу NewScores, поэтому она не может быть найдена. Просто объедините эту таблицу.

Если вы действительно хотите избежать прямого соединения, вы можете заменить NewScores.NetScore на SELECT NetScore FROM NewScores WHERE {условия, по которым они должны совпадать}.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь