我不知道此问题是否曾被提出过。但是在查找varchars时遇到问题。
让我解释一下:
我有这张桌子:
CREATE TABLE Table1
(
[Field] [varchar](10) NOT NULL
)
INSERT INTO Table1
VALUES('1'),('2'),('3'),('4'),('5'),('TITLE')
我喜欢输出是这样的:
'[TITLE],[1],[2],[3],[4],[5]'
我想要' TITLE'先订购然后1,2,3,4,5
因此,此查询将返回有序结果。我没有比'TITLE'
更长的数字SELECT
*
FROM
Table1
ORDER BY
LEN([Field]) DESC,
[Field] ASC
然后我通常会像这样连接varchar:
DECLARE @cols VARCHAR(MAX)
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]),
QUOTENAME([Field]))
FROM
Table1
ORDER BY
LEN([Field]) DESC,
[Field] ASC
但这回归:
'[5]'
我觉得这很奇怪。有人可以解释一下原因吗?
我知道有一种替代varchar的替代解决方案。像这样:
DECLARE @cols VARCHAR(MAX)
SELECT @cols=STUFF
(
(
SELECT
',' +QUOTENAME([Field])
FROM
Table1
ORDER BY
LEN([Field]) DESC,
[Field] ASC
FOR XML PATH('')
)
,1,1,'')
这将返回我的预期结果:
'[TITLE],[1],[2],[3],[4],[5]'
修改
建议@cols
在开始时无效。因为如果我删除order by
。像这样:
DECLARE @cols VARCHAR(MAX)
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]),
QUOTENAME([Field]))
FROM
Table1
我的结果将是这样的:
'[1],[2],[3],[4],[5],[TITLE]'
EDIT1
这不起作用:
DECLARE @cols VARCHAR(MAX)
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]),
QUOTENAME([Field]))
FROM(
SELECT [Field]
FROM
Table1
ORDER BY
LEN([Field]) DESC,
[Field] ASC
) AS t
因为它会发出如下的异常消息:
Msg 1033,Level 15,State 1,Line 17 ORDER BY子句无效 视图,内联函数,派生表,子查询和公用表 表达式,除非还指定了TOP或FOR XML。
EDIT2
像我预期的那样。我不能这样做:SELECT @cols, @cols = COALESCE(@cols + ','+QUOTENAME([Field]),
QUOTENAME([Field]))
FROM
Table1
ORDER BY
LEN([Field]) DESC,
[Field] ASC
因为这会引发这样的异常:
消息141,级别15,状态1,行9指定a的SELECT语句 变量的值不得与数据检索相结合 操作
答案 0 :(得分:3)
我不确定,但我认为答案是在查询的执行顺序中。我尝试过以下代码:
DECLARE @x INT
SET @x = 0
SELECT @x =@x + 1
FROM
Table1
ORDER BY
LEN(Field) DESC, Field ASC
SELECT @x
然后返回1,
DECLARE @x INT
SET @x = 0
SELECT @x =@x + 1
FROM
Table1
SELECT @x
返回6,这最多是奇数。
但是,从第一个查询的执行计划可以看出事件的顺序是:
Table Scan -> Compute Scalar -> Sort -> Select
所以我最好的猜测是首先计算结果,然后排序,最后得到一些中间值。
恕我直言,这是滥用SQL服务器执行引擎,基本上是未定义的行为。即使你设法让它在这个SQL服务器上工作,也不知道服务包是否会为你破解它。我会选择你所描述的第二种解决方案,它是直截了当的,更容易维护。关于edit1:指定SELECT TOP 100 PERCENT
负责“视图中没有排序”错误,但是,SQL服务器做了一些魔术,你仍然最终得到[1],[2],[3],[4],[5],[TITLE]
答案 1 :(得分:2)
您可以查看这篇文章PRB: Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location
ANSI SQL-92规范要求引用的任何列 ORDER BY子句匹配由列定义的结果集 出现在SELECT列表中。将表达式应用于成员时 ORDER BY子句,结果列未公开 SELECT列表,导致未定义的行为。
在order by子句中使用表达式时,会得到不同的执行计划。
排序在Compute Scalar之后而不是之前应用。
将字符串与顺序连接的安全方法是使用for xml
。