#sql-server #tsql #sql-order-by #dynamic-sql
#sql-сервер #tsql #sql-order-by #dynamic-sql
Вопрос:
У меня есть следующая хранимая процедура MS SQL. Мне нужно отсортировать результаты без использования динамического SQL и sp_executesql
метода
@Order by может иметь возможные значения ProductName ASC
, ProductName DESC
, ProductCode ASC
VendorName DESC
, VendorCode
,,, или ClientName
Я пытался использовать ORDER BY CASE
, есть ли какая-либо проблема, если ProductName
, ProductCode
имеют разный тип?
ALTER PROCEDURE [dbo].[SortedReport]
(
@ClientID INT,
@RecordLimit,
@FromDate DATETIME,
@ToDate DATETIME,
@OrderBy NVARCHAR(MAX)
)
AS
BEGIN
IF (@OrderBy IS NULL) BEGIN
SET @OrderBy = 'ProductName';
END
SELECT TOP (@RecordLimit)
sv.ClientID,
sv.VendorID,
sv.ProductID,
sv.TransactionTime,
sv.ClientName,
sv.VendorName,
sv.ProductName,
sv.ProductCode,
sv.VendorCode,
FROM SortedReportiew AS sv
WHERE (sv.ClientID = @ClientID)
AND (sv.TransactionTime >= @FromDate)
AND (sv.TransactionTime < @Date)
Обновить:
Правильна ли приведенная ниже часть? ссылка из здесь
ORDER BY
CASE @OrderBy WHEN 'ProductCode ASC' THEN ProductCode WHEN 'ProductCode DESC' THEN ProductCode END DESC,
CASE @OrderBy WHEN 'ProductName ASC' THEN ProductName WHEN 'ProductName DESC' THEN ProductName END DESC,
Комментарии:
1. Почему не динамический SQL? Это намного быстрее, чем любое из статических решений для такого рода задач.
2. Почему вы хотите избежать динамического SQL для выполнения динамической инструкции?
3. @RBarryYoung, @Markus Winand, просто потому, что клиент хочет преобразовать эти динамические SQL в статические
4. Итак, спросите клиента, зачем это делать 😉 Существует » миф о том, что динамический SQL работает медленно «, который часто приводит к подобным запросам. Однако правильно выполненный dynamic-sql (с использованием параметров привязки), как правило, лучше.
5. @RBarryYoung: избавление от динамического sql для «order by» приводит к повышению производительности в этих запросах order by.
Ответ №1:
Как вы уже сказали: используйте ORDER BY CASE
, но несколько раз, чтобы избежать проблем с разными типами столбцов:
...
ORDER BY
CASE WHEN @OrderBy ='ProductName ASC' THEN sv.ProductName END,
CASE WHEN @OrderBy ='ProductName DESC' THEN sv.ProductName END DESC,
CASE WHEN @OrderBy ='ProductCode ASC' THEN sv.ProductCode END,
CASE WHEN @OrderBy ='ProductCode DESC' THEN sv.ProductCode END DESC,
CASE WHEN @OrderBy ='VendorName ASC' THEN sv.VendorName END,
CASE WHEN @OrderBy ='VendorName DESC' THEN sv.VendorName END DESC,
CASE WHEN @OrderBy ='VendorCode' THEN sv.VendorCode END,
CASE WHEN @OrderBy ='ClientName' THEN sv.ClientName END
Редактировать:
Обновил запрос, чтобы соответствовать вашему обновленному вопросу. Я полагаю, вы имели в виду ProductCode ASC
и ProductCode DESC
?
Комментарии:
1. Пожалуйста, смотрите обновленный вопрос, @OrderBy также содержит направление сортировки, подобное
ProductName ASC
2. ASC / DESC является необязательным, поскольку ASC используется по умолчанию: msdn.microsoft.com/en-us/library/ms188385.aspx
Ответ №2:
Я понимаю, порядок использует только один столбец. В этом случае я мог бы попробовать что-то вроде этого:
-
Разделить
@OrderBy
на@OrderByCol
и@OrderByDir
. -
Используйте этот шаблон:
... ORDER BY CASE @OrderByDir WHEN 'ASC' THEN CASE @OrderByCol WHEN 'Column1' THEN Column1 WHEN 'Column2' THEN Column2 ... END END ASC, CASE @OrderByDir WHEN 'DESC' THEN CASE @OrderByCol WHEN 'Column1' THEN Column1 WHEN 'Column2' THEN Column2 ... END END DESC
Или, если вы используете SQL Server 2005 , возможно, этот, в качестве альтернативы:
WITH sorted AS ( SELECT ... /* columns, omitted */ Column1Order = ROW_NUMBER() OVER (ORDER BY Column1), Column2Order = ROW_NUMBER() OVER (ORDER BY Column2), ... FROM ... ) SELECT ... FROM sorted ORDER BY CASE @OrderByCol WHEN 'Column1' THEN Column1Order WHEN 'Column2' THEN Column2Order ... END * CASE @OrderByDir WHEN 'DESC' THEN -1 ELSE 1 END
Как @Greg Ogle правильно указал в комментарии, первый шаблон может работать только тогда, когда различные критерии сортировки имеют совместимые типы, в противном случае инструкция будет прервана.
Комментарии:
1. Обратите внимание, что ORDER BY должны быть одного и того же типа данных для каждого СЛУЧАЯ, иначе будет выдана ошибка преобразования.
2. Спасибо, я добавил примечание к своему ответу (не знаю, почему я не смог этого сделать, когда отправлял ответ).