2015-04-30 2 views
0

У меня есть запрос, как это:ORDER BY клаузулы не сортировать по псевдониму в SQL Server

DECLARE @Sortorder VARCHAR(5) = 'asc', 
     @ColumnNumber INT = 9 

SELECT 
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId 
FROM [tasks].[WorkItems] w 
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId 
WHERE 
    w.[ShowInTaskList] = 1 AND UserName IS NOT NULL 
ORDER BY 
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc' THEN UserName END ASC, 
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN UserName END DESC 

Когда я делаю, что данные не отсортированы по нику в любом возрастанию порядке или по алфавиту, но когда я делаю это:

SELECT 
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId 
FROM [tasks].[WorkItems] w 
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId 
WHERE 
    w.[ShowInTaskList] = 1 AND UserName IS NOT NULL 
ORDER BY 
    UserName 

Что я делаю неправильно в динамическом порядке? Значения одинаковы в объявленных переменных и в случае. Чтобы быть откровенным, я не знаю, какие ключевые слова я должен передать google;) Большое спасибо за ответ.

+1

Как вы можете заказывать по имени пользователя по алфавиту, так и по алфавиту, в то же время. Я что-то упускаю? оба утверждения вашего заказа будут истинными. –

+0

wow не ожидал этого, спасибо !! пожалуйста, ответьте на мой вопрос, чтобы я мог дать большие пальцы;) –

+0

Как вы думаете, оба заказа по заявлениям верны? Это зависит от того, что будет храниться в переменной '@ SortOrder' ... – veljasije

ответ

2

У вас есть столбец UserName и псевдоним UserName. Это столбец значение, которое используется для сортировки результатов, а не псевдонима. Хотя вполне приемлемо использовать псевдоним внутри предложения ORDER BY, он не может использоваться внутри оператора CASE WHEN.

Решение использовать подзапрос (или КТР):

DECLARE 
    @Sortorder VARCHAR(5) = 'asc', 
    @ColumnNumber INT = 9 

SELECT * FROM (
    SELECT SUBSTRING(csu.UserName, /* removed for readability */) AS UserNameCopy, w.WorkItemId 
    FROM [tasks].[WorkItems] w 
    LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId 
    WHERE w.[ShowInTaskList] = 1 AND UserName IS NOT NULL 
) AS SubQuery 
ORDER BY 
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc' THEN SubQuery.UserNameCopy END ASC, 
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN SubQuery.UserNameCopy END DESC 
+0

Почему это не сбой при @ColumnNumber = 7? Моя первая реакция заключалась в том, что он должен потерпеть крах, поскольку это похоже на запись 'order by asc desc' (без написания имен столбцов!), Но это не так. Зачем? –

+1

@ ZoharPeled, потому что он будет заказывать по нулевому значению, а любое жестко закодированное значение - пример: order by null, null, 2015, '' a 'desc –

+0

@ t-clausen.dk: Хорошо, я вижу свою ошибку, это похоже на запись 'order по null asc, null desc'. благодаря! –

0

Я думаю, что вы можете добиться этого легко с помощью динамического SQL (он работал для меня):

DECLARE @statement NVARCHAR(MAX) , 
     @SortOrder VARCHAR(5) = 'desc' , 
     @columnNumber INT = 9 


SET @statement = N' 
SELECT 
    SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1, LEN(csu.UserName)) as UserName, w.WorkItemId 
FROM [tasks].[WorkItems] w 
    LEFT JOIN operations.CustomerServiceUser csu 
     ON csu.UserId = w.AssignedToUserId 
WHERE  
    w.[ShowInTaskList] = 1 
    AND UserName is not null 
ORDER BY' +    
     CASE 
      WHEN (@ColumnNumber = 9 AND @SortOrder = 'asc') THEN 'UserName ASC' 
      WHEN (@columnNumber = 9 AND @SortOrder = 'desc') THEN 'UserName DESC' 
      ELSE 'CustomerId' END 


EXEC sys.sp_executesql @statement 
GO 
0

Я считаю, что легкий и безопасный способ заключается в использовании КТР:

;WITH CTE AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY UserName ASC) As AscOrder, 
      ROW_NUMBER() OVER (ORDER BY UserName DESC) As DescOrder, 
     -- editor note: CHARINDEX is for '\' and not '\ ', but it messes up the code coloring system of SO, so I've added a space. 
     SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1,LEN(csu.UserName)) as UserName, w.WorkItemId 
    FROM [tasks].[WorkItems] w 
    LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId 
    WHERE w.[ShowInTaskList] = 1 
    AND UserName is not null 
) 

SELECT * 
FROM CTE 
ORDER BY CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc' THEN AscOrder 
       WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN DescOrder 
     END 
0

Вы можете использовать CROSS APPLY, чтобы сделать ваш код выглядит более удобным. Это не влияет на производительность:

DECLARE 
    @Sortorder VARCHAR(5) = 'asc' , 
    @ColumnNumber INT = 9; 

SELECT 
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, 
      u.UserName , 
    w.WorkItemId 
FROM 
    [tasks].[WorkItems] w 
    LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId 
    CROSS APPLY (SELECT LEN(csu.UserName) AS UserName) u 
WHERE 
    w.[ShowInTaskList] = 1 
    AND UserName IS NOT NULL 
ORDER BY 
    CASE WHEN @ColumnNumber = 9 
       AND @Sortorder = 'asc' THEN u.UserName 
    END ASC , 
    CASE WHEN @ColumnNumber = 9 
       AND @Sortorder = 'desc' THEN u.UserName 
    END DESC; 

И пример с данными:

CREATE TABLE #a (aColumn INT, b INT); 

INSERT INTO #a 
VALUES 
     (1, 1), 
     (1, 2), 
     (2, 1), 
     (3, 1), 
     (1, 3), 
     (4, 4); 

DECLARE 
    @Sortorder VARCHAR(5) = 'asc' , 
    @ColumnNumber INT = 9; 

SELECT 
    aColumn , 
    b aColumn 
FROM 
    #a tbl 
    CROSS APPLY (
        SELECT 
        CAST((tbl.aColumn + 1 - 2) * 5 AS VARCHAR(100)) r /*or any other kind of operation, such as substring etc*/ 
       ) shortcut 
ORDER BY 
    CASE WHEN @ColumnNumber = 9 
       AND @Sortorder = 'asc' THEN shortcut.r 
    END ASC , 
    CASE WHEN @ColumnNumber = 9 
       AND @Sortorder = 'desc' THEN shortcut.r 
    END DESC; 


DROP TABLE #a; 
Смежные вопросы