USE AdventureWorks2014
SELECT
result.BusinessEntityID,
p.FirstName, p.LastName,
result.TotalSales, '2011' AS SalesYear,
CASE
WHEN CAST(result.TotalSales AS int) > 1000000 THEN 'MillionPlus'
WHEN CAST(result.TotalSales AS int) < 100000 THEN 'Warning'
ELSE 'Met Expectations'
END AS BonusCategory
FROM
person.Person AS P,
(SELECT sp.BusinessEntityID, FORMAT(sum(soh.SubTotal), 'c', 'en-us') AS TotalSales
FROM sales.SalesPerson as sp
RIGHT JOIN sales.SalesOrderHeader as SOH ON sp.BusinessEntityID = soh.SalesPersonID
WHERE soh.orderdate LIKE '%2011%'
GROUP BY sp.BusinessEntityID) AS result
WHERE
result.BusinessEntityID = p.BusinessEntityID
OR result.TotalSales IS NULL
ORDER BY
result.BusinessEntityID
Полное сообщение об ошибке
Сообщение 245, уровень 16, состояние 1, строка 2
Ошибка преобразования при преобразовании значения nvarchar "28 926,25 долл. США" в тип данных int.
@LukaszSzozda Сообщение 4104, уровень 16, состояние 1, строка 9 Не удалось связать составной идентификатор «result.TotalSales». введите свое решение, и вот что я получил
Не используйте соединения старого стиля. Хуже всего смешивание синтаксиса старого стиля и нового (лучшего) синтаксиса соединения в одном запросе.
Что-то, что нужно понимать, когда программирование почти на ЛЮБОЙ платформе преобразует числовые значения, такие как 123.45
, в строковые или текстовые значения, такие как "123.45"
, — это удивительно медленная и дорогая операция. Они могут выглядеть одинаково, но это разные значения, и во многом благодаря интернационализации/культурным проблемам преобразования между ними не являются тривиальными. Всегда стремитесь свести к минимуму эти преобразования, а когда они вам нужны, оставьте это до последнего момента.
SQL Server здесь не исключение. Это может быть очень придирчиво к смешиванию между числами и текстом.
Для этого вопроса вложенный внутренний запрос принимает выражение sum(soh.SubTotal)
, которое является числом, и оборачивает его в вызов функции FORMAT()
, который создает текстовое поле. Позже мы попытаемся использовать результат во внешнем запросе, как будто это снова число.
Не делай этого!
Подождите, чтобы отформатировать результат до предложения SELECT
внешнего оператора в последний возможный момент. Это позволяет нам полностью удалить CAST()
внутри выражения CASE
.
Кроме того, НИКОГДА не используйте старый синтаксис соединения A,B WHERE
. Он устарел уже более 25 лет.
USE AdventureWorks2014
SELECT result.BusinessEntityID, p.FirstName, p.LastName,
FORMAT(result.TotalSales,'c','en-us') As TotalSales, '2011' as SalesYear,
CASE
WHEN result.TotalSales > 1000000 THEN 'MillionPlus'
WHEN result.TotalSales < 100000 THEN 'Warning'
ELSE 'Met Expectations'
END as BonusCategory
FROM person.Person as P
INNER JOIN (
SELECT sp.BusinessEntityID, FORMAT(sum(soh.SubTotal),'c','en-us') as TotalSales
FROM sales.SalesPerson as sp
RIGHT JOIN sales.SalesOrderHeader as SOH
ON sp.BusinessEntityID = soh.SalesPersonID
WHERE soh.orderdate LIKE '%2011%'
GROUP BY sp.BusinessEntityID
) result ON (result.BusinessEntityID = p.BusinessEntityID OR result.TotalSales is null)
ORDER BY result.BusinessEntityID
Даже лучше, даже не конвертируйте в строку/текст в предложении SELECT! Позвольте клиентской программе или инструменту создания отчетов справиться с этой частью. Это еще один способ следовать совету «оставить преобразование на самый последний момент» в первом абзаце.
FORMAT(sum(soh.SubTotal),'c','en-us')
->CAST(result.TotalSales AS int)
Форматирование вывода (при необходимости) должно выполняться в последнюю очередь