#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
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 ' 11%'
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.
Комментарии:
1.
FORMAT(sum(soh.SubTotal),'c','en-us')
->CAST(result.TotalSales AS int)
Форматирование вывода (при необходимости) должно выполняться в последнюю очередь2. @LukaszSzozda Сообщение 4104, уровень 16, состояние 1, строка 9 Многосоставный идентификатор «результат. Не удалось привязать итоговые продажи. введите свое решение, и это то, что я получил
3. Не используйте объединения в старом стиле . Хуже всего смешивание синтаксиса старого стиля и нового (наилучшего) синтаксиса объединения в одном запросе.
Ответ №1:
При программировании практически на ЛЮБОЙ платформе необходимо понимать, что преобразование числовых значений типа like 123.45
в строковые или текстовые значения типа like "123.45"
является удивительно медленной и дорогостоящей операцией. Они могут выглядеть одинаково, но это разные значения, и во многом благодаря интернационализации / культурным проблемам преобразования между ними не являются тривиальными. Всегда стремитесь минимизировать эти преобразования, и когда они вам понадобятся, оставьте это до последнего возможного момента.
SQL Server здесь не исключение. Он может быть очень требовательным к смешиванию чисел и текста.
Для этого вопроса вложенный внутренний запрос принимает sum(soh.SubTotal)
выражение, представляющее собой число, и оборачивает его в FORMAT()
вызов функции, который создает текстовое поле. Позже мы попытаемся использовать результат во внешнем запросе, как если бы это снова было число.
Не делайте этого!
Подождите, чтобы отформатировать результат до SELECT
предложения внешнего оператора, в последний возможный момент. Это позволяет нам полностью удалить CAST()
s из 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 ' 11%'
GROUP BY sp.BusinessEntityID
) result ON (result.BusinessEntityID = p.BusinessEntityID OR result.TotalSales is null)
ORDER BY result.BusinessEntityID
Еще лучше, даже не преобразовывайте в строку / текст в предложении SELECT!Пусть клиентская программа или средство создания отчетов обработают эту часть. Это еще один способ, которым мы можем следовать указаниям «оставить преобразование до последнего возможного момента» в первом абзаце.