Ms sql select в select: Вложенные запросы (SQL Server) — SQL Server

Не получается сделать SELECT FROM SELECT [MS SQL Server]


Вопрос задан


Изменён
5 лет 4 месяца назад


Просмотрен
26k раза

Есть таблица Сотрудники (Employees) и Отделы (Departments).
Необходимо найти такие отделы, в которых суммарная зарплата сотрудников будет наибольшей.
Вот наполнение самих таблиц

Дошел только до того, что нашел максимальную сумму

SELECT MAX(A.SUM_Money)
FROM (
    SELECT Dep_number, SUM(Cash_bonus + Salary) AS SUM_Money
    FROM Employees
    GROUP BY Dep_number
) AS A

Только вот никак не могу вывести рядом поле с номером отдела

SELECT A.Dep_number, MAX(A.SUM_Money)
FROM (
    SELECT Dep_number, SUM(Cash_bonus + Salary) AS SUM_Money
    FROM Employees
    GROUP BY Dep_number
) AS A

Пишет ошибку:

Сообщение 8120, уровень 16, состояние 1, строка 3

Столбец «A. Dep_number» недопустим в списке выбора, поскольку он не содержится ни в статистической функции, ни в предложении GROUP BY.

Подскажите как быть?

  • sql
  • sql-server
  • sql-server-2008

Вообще, группировка должна быть в том запросе, в котором используется аггрегация. Так что запрос будет таким:

SELECT A.Dep_number, MAX(A.SUM_Money)
FROM (
    SELECT Dep_number, SUM(Cash_bonus + Salary) AS SUM_Money
    FROM Employees
    GROUP BY Dep_number
) AS A
GROUP BY A.Dep_Number.

Но это не то, что нам нужно, поскольку для каждого Dep_Number у нас в запросе только одна запись.
Можно просто отсортировать по SUM_Money по убыванию и взять первую запись:

SELECT TOP 1 A.Dep_number, A.SUM_Money
FROM (
    SELECT Dep_number, SUM(Cash_bonus + Salary) AS SUM_Money
    FROM Employees
    GROUP BY Dep_number
) AS A
ORDER BY A.SUM_Money DESC

Но отделов с одинаковой суммой может быть несколько. Поэтому добавим ранжирование в подзапрос:

    SELECT A. Dep_number, A.SUM_Money
    FROM (
        SELECT rank() over(order by sum(cash_bonus+Salary) desc) rank, 
        Dep_number, SUM(Cash_bonus + Salary) AS SUM_Money
        FROM Employees
        GROUP BY Dep_number
    ) AS A
where rank=1

фиддл







Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации


Почта

Необходима, но никому не показывается




Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки


SQL-Урок 11.

Выборка уникальных данных (SELECT DISTINCT)

Базы данных

Оператор SQL DISTINCT используется для указания на то, что следует работать только с уникальными значениями столбца.

Оператор SQL DISTINCT нашел широкое применение в операторе SQL SELECT, для выборки уникальных значений. Так же используется в агрегатных функциях.

Синтаксис

При выборке:

SELECT DISTINCT поле FROM имя_таблицы WHERE условие

При подсчете:

SELECT COUNT(DISTINCT поле) FROM имя_таблицы WHERE условие

При суммировании:

SELECT SUM(DISTINCT поле) FROM имя_таблицы WHERE условие

Примеры

Все примеры будут по этой таблице workers, если не сказано иное:

idnameagesalary
1Дима23400
2Петя25500
3Вася23500
4Коля301000
5Иван27500
6Кирилл281000

Пример 

Давайте выберем все уникальные значения зарплат из таблицы workers:

SELECT DISTINCT salary FROM workers

SQL запрос выберет следующие строки:

salary
400
500
1000

Пример 

Давайте подсчитаем все уникальные значения зарплат из таблицы workers (их будет 3 штуки: 400, 500 и 1000):

SELECT COUNT(DISTINCT salary) as count FROM workers

SQL запрос выберет следующие строки:

count
3

Пример 

Давайте подсчитаем одновременно все уникальные значения зарплат и уникальные значения возрастов и запишем их в разные поля:

SELECT
	COUNT(DISTINCT salary) as salary_count,
 	COUNT(DISTINCT age) as age_count
FROM workers

SQL запрос выберет следующие строки:

salary_countage_count
35

Пример 

Давайте просуммируем все уникальные значения зарплат из таблицы workers:

SELECT SUM(DISTINCT salary) as sum FROM workers

SQL запрос выберет следующие строки:

sum
1900

Вложенный оператор select в SQL Server

спросил

Изменено
7 месяцев назад

Просмотрено
949 тысяч раз

Почему не работает следующее?

 ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте)
 

Думаю, мое понимание SQL неверно, потому что я думал, что это вернет то же самое, что и

 ВЫБЕРИТЕ имя ИЗ информации об агенте
 

Разве внутренний оператор select не создает результирующий набор, который затем запрашивает внешний оператор SELECT?

  • sql
  • sql-сервер
  • вложенный
  • подзапрос
  • запрос

Вам нужно псевдоним подзапроса.

 ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте) a
 

или, чтобы быть более точным,

 SELECT a.name FROM (SELECT name FROM agentinformation) a
 

4

Ответ Джо Стефанелли уже верен.

 ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте) как
 

Нам нужно создать псевдоним подзапроса, потому что для запроса требуется табличный объект, который мы получим, создав псевдоним для подзапроса. Концептуально результаты подзапроса подставляются во внешний запрос. Поскольку нам нужен объект таблицы во внешнем запросе, нам нужно создать псевдоним внутреннего запроса.

Операторы, включающие подзапрос, обычно принимают одну из следующих форм:

  • WHERE выражение [NOT] IN (подзапрос)
  • ГДЕ выражение оператор сравнения_[ЛЮБОЙ | ВСЕ] (подзапрос)
  • ГДЕ [НЕ] СУЩЕСТВУЕТ (подзапрос)

Проверьте дополнительные правила и типы подзапросов.

Дополнительные примеры вложенных подзапросов.

  1. IN / NOT IN — этот оператор берет выходные данные внутреннего запроса после выполнения внутреннего запроса, которые могут содержать ноль или более значений, и отправляет их во внешний запрос. Затем внешний запрос извлекает все совпадающие строки [оператор IN] или не совпадающие строки [оператор NOT IN].

  2. ЛЮБОЙ — [> ЛЮБОЙ или ЛЮБОЙ оператор берет список значений, созданных внутренним запросом, и извлекает все значения, которые больше минимального значения списка.

напр. >ANY(100,200,300), оператор ANY извлечет все значения больше 100.

  1. ALL – [>ALL или ALL оператор берет список значений, созданных внутренним запросом, и извлекает все значения, которые больше максимального списка.

напр. >ALL(100,200,300), оператор ALL выберет все значения больше 300.

  1. EXISTS – Ключевое слово EXISTS создает логическое значение [ИСТИНА/ЛОЖЬ]. EXISTS проверяет наличие строк, возвращаемых подзапросом.

0

ПОПРОБУЙТЕ ЭТО

 'выберите *,(ВЫБЕРИТЕ количество (id) ИЗ продуктов, ГДЕ user_id = users.id) как products_count от пользователей ORDER BY products_count DESC, ID DESC LIMIT 200
 

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Требуется, но никогда не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

сервер sql — выбор SQL из запроса на выборку

Я хочу сделать запрос на выбор, который выполняет первый выбор, а затем использует этот выбор для выполнения второго выбора.

Я сделал 1-ю версию, используя временную таблицу, но хотел бы знать, есть ли способ сделать это без временной таблицы

мой код с временной таблицей выглядит так:

 select dvd_name, book_name, count(*) nb
в #t
из США
книга внутреннего соединения на usr_book_id = book_id
внутреннее соединение dvd на dvd_id = usr_dvd_id
сгруппировать по dvd_name, book_name
имея количество (*)> 1
выберите 10 лучших usr_smthg, #t.book_name,dvd_name
от #т
книга внутреннего соединения b на b.book_name = #t.book_name
внутреннее соединение usr на usr_book_id = book_id
 
  • sql
  • sql-server

Вы можете использовать CTE для этого

 с т как
(
    выберите dvd_name, book_name, count(*) nb
    из США
    книга внутреннего соединения на usr_book_id = book_id
    внутреннее соединение dvd на dvd_id = usr_dvd_id
    сгруппировать по dvd_name, book_name
    имея количество (*)> 1
)
выберите 10 лучших usr_smthg, t.book_name,dvd_name
от т
книга внутреннего соединения b на b. book_name = t.book_name
внутреннее соединение usr на usr_book_id = book_id
 

4

В sql вы можете использовать подзапрос, например:

 выберите 10 лучших usr.usr_smthg, t.book_name, usr.dvd_name
от (
  выберите dvd_name, book_name, count(*) nb
  из США
  книга внутреннего соединения на usr_book_id = book_id
  внутреннее соединение dvd на dvd_id = usr_dvd_id
  сгруппировать по dvd_name, book_name
  имея количество (*)> 1
) т
книга внутреннего соединения b на b.book_name = t.book_name
внутреннее соединение usr на usr_book_id = book_id
-- предполагать
заказать по убыванию n.n.b.
 

Вы можете использовать оконную функцию с подзапросом:

 select top (10) t.usr_smthg, t.book_name, t.dvd_name
из (выберите usr_smthg, book_name, dvd_name,
             count(*) over (раздел по dvd_name, book_name) как cnt
      из внутреннего соединения usr
           книга
           on usr_book_id = внутреннее соединение book_id
           DVD
           на dvd_id = usr_dvd_id
     ) т
 где снт > 1
 Сортировать по ??;
 

?? указывает столбец заказа на основе того, что вы хотите верхних (10) записей.