Не могу собрать запрос MSSQL
Есть 3 таблицы: Countries, Brands, Cars. Вот фиддл, с готовыми таблицами: http://sqlfiddle.com/#!18/34629/63
Задача: Вывести список самых дешевых автомобилей каждой марки (название авто + название марки)
Попытка решения:
select top 1 Cars.Name, Brands.Name, min(Price) from Cars
join Brands on Cars.BrandID = Brands.ID
group by Cars.Name
ORDER BY min(Price)
Подскажите, в каком направлении копать?
Ответы (2 шт):
top 1выглядит излишним. Вы уже группируете по марке.- В задании выше у вас не написано про порядок вывода.
ORDER BY min(Price)тогда излишен, при автоматической проверке может вызывать отказ.
Да и избыточность кода это повышает, если нет условия обязательного.
Предлагаемый код (убрал прежний нерабочий код, дописал новый):
select Cars.Name, Brands.Name, Price
from Cars
join Brands on Cars.BrandID = Brands.ID
WHERE (BrandID, Price) IN
(SELECT BrandID, min(Price)
FROM Cars
GROUP BY BrandID);
Я знаю mySQL, а не sql-server, не получилось запустить в фиддле, выдает ошибку (указал ниже). Но в mySQL я получил результат:
Query result:
+-----------+------------+-------+
| Name | Name | Price |
+-----------+------------+-------+
| Rio | KIA | 734 |
| Solaris | Hyundai | 746 |
| Granta | LADA | 404 |
| Corolla | Toyota | 1173 |
| Outlander | Mitsubishi | 1449 |
| Qashqai | Nissan | 1120 |
+-----------+------------+-------+
Affected rows: 6
Ошибка в фиддле: "An expression of non-boolean type specified in a context where a condition is expected, near ','."
В MS SQL есть такая штука TOP 1 WITH TIES. Вот как это будет выглядеть:
SELECT TOP 1 WITH TIES
Cars.Name, Brands.Name, Cars.Price
FROM Cars
INNER JOIN Brands ON Cars.BrandID = Brands.ID
ORDER BY ROW_NUMBER() OVER ( PARTITION BY Cars.BrandID ORDER BY Cars.Price )
Второй способ, дающий аналогичный результат:
SELECT
SQ.CarsName, SQ.BrandsName, SQ.Price
FROM
(
SELECT RANK() OVER ( PARTITION BY Cars.BrandID ORDER BY Cars.Price )
AS RankRow,
Cars.Name AS CarsName, Brands.Name AS BrandsName, Cars.Price AS
Price
FROM Cars
INNER JOIN Brands ON Cars.BrandID = Brands.ID
) SQ
WHERE SQ.RankRow = 1
Рабочий вариант, предложенный Сергеем будет выглядеть так:
SELECT
c.Name AS CarsName,
SQ.BrandName AS BrandName,
c.Price AS Price
FROM Cars c
INNER JOIN
(
SELECT
b.ID AS BrandID, b.Name AS BrandName, MIN(c.Price) AS Price
FROM Cars c
INNER JOIN Brands b ON c.BrandID = b.ID
GROUP BY b.ID, b.Name
) SQ ON c.Price = SQ.Price AND c.BrandID = c.BrandID
В этом случае результат скорее подогнанный, потому что делать JOIN по цене как то плохо выглядит, а включить Cars.Name в GROUP BY мы не можем, получим не правильный результат.