我有这样的查询:
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
当我这样做时,数据不按用户名按任何顺序asc或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;)非常感谢您的回答。
答案 0 :(得分:2)
您有列UserName
和别名UserName
。 列值用于对结果进行排序,而不是别名。虽然在ORDER BY
子句中使用别名是完全可以接受的,但它不能在CASE WHEN
语句中使用。
解决方案是使用子查询(或CTE):
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
答案 1 :(得分:1)
您可以使用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;
答案 2 :(得分:0)
我认为您可以使用Dynamic 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
答案 3 :(得分:0)
我认为简单安全的方法是使用CTE:
;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