我有 SQL Server 存储过程:
Select
A.Id, A.Title, A.BriefText,
I.ArticleView, U.DisplayName AS Author,
U.Avatar,
(SELECT COUNT(*) FROM Articles_Like WHERE ArticleId = A.Id) AS Likes,
(SELECT COUNT(*) FROM Articles_Comment WHERE ArticleId = A.Id) AS Comments,
CASE
WHEN EXISTS (SELECT Id FROM Articles_Like
WHERE ArticleId = A.Id AND UserId = @UserId)
THEN 1
ELSE 0
END AS IsLiked,
CASE
WHEN EXISTS (SELECT Id FROM Articles_Bookmark
WHERE ArticleId = A.Id AND UserId = @UserId)
THEN 1
ELSE 0
END AS IsBookmarked
FROM
Articles A
LEFT OUTER JOIN
Articles_Info I ON I.ArticleId = A.Id
LEFT OUTER JOIN
Users_Info U ON U.UserId = A.UserId
GROUP BY
A.Title, A.BriefText, A.Id, I.ArticleView,
U.DisplayName, U.Avatar, U.UserId
ORDER BY
CASE WHEN @orderby = 1 THEN A.Id END DESC,
CASE WHEN @orderby = 2 THEN I.ArticleView END DESC,
END DESC
CASE WHEN @orderby = 3 THEN Likes END DESC
最后一行
CASE WHEN @orderby = 3 THEN Likes END DESC
我收到错误:
列名无效
当我使用
CASE
别名时不再起作用,我该如何解决这个问题?
我可以使用:
CASE WHEN @orderby = 3 THEN (SELECT COUNT(*) FROM Articles_Like WHERE ArticleId = A.Id) END DESC
像这样:
Select A.Id, A.Title, A.BriefText, I.ArticleView, U.DisplayName AS Author, U.Avatar,
(SELECT COUNT(*) FROM Articles_Like WHERE ArticleId=A.Id) AS Likes,
(SELECT COUNT(*) FROM Articles_Comment WHERE ArticleId=A.Id) AS Comments,
CASE WHEN EXISTS (SELECT Id FROM Articles_Like WHERE ArticleId=A.Id AND UserId=@UserId)
THEN 1 ELSE 0 END AS IsLiked,
CASE WHEN EXISTS (SELECT Id FROM Articles_Bookmark WHERE ArticleId=A.Id AND UserId=@UserId)
THEN 1 ELSE 0 END AS IsBookmarked
FROM Articles A
LEFT OUTER JOIN Articles_Info I ON I.ArticleId = A.Id
LEFT OUTER JOIN Users_Info U ON U.UserId = A.UserId
GROUP BY A.Title, A.BriefText, A.Id, I.ArticleView, U.DisplayName, U.Avatar, U.UserId
ORDER BY
CASE WHEN @orderby=1 THEN A.Id END DESC,
CASE WHEN @orderby=2 THEN I.ArticleView END DESC,
CASE WHEN @orderby=3 THEN (SELECT COUNT(*) FROM Articles_Like WHERE ArticleId=A.Id) END DESC
它有效,但我在存储过程的顶部使用了这段代码,这不是两次使用代码的正确方法。
我正在使用 SQL Server 2022
如果 ORDER BY 子句引用选择列表中的列别名,则该列别名必须单独使用,而不能作为 ORDER BY 子句中某些表达式的一部分,例如:
Copy
SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName; -- correct
SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName + ''; -- wrong
您可以在以下工作/非工作示例中看到您遇到的相同情况:
CREATE TABLE test (id int, f1 varchar(20));
INSERT INTO test VALUES (1, 'foo');
INSERT INTO test VALUES (2, 'bar');
/*runs fine*/
SELECT id, (SELECT count(*) FROM test) as total_count
FROM test
ORDER BY total_count
/*errors*/
SELECT id, (SELECT count(*) FROM test) as total_count
FROM test
ORDER BY CASE WHEN 1=1 THEN total_count END
dbfiddle here 正在执行此操作。
为了避免代码重复,请考虑将不带 ORDER BY 的查询放入子查询中,然后在主查询中排序:
SELECT *
FROM
(
Select A.Id, A.Title, A.BriefText, I.ArticleView, U.DisplayName AS Author, U.Avatar,
(SELECT COUNT(*) FROM Articles_Like WHERE ArticleId=A.Id) AS Likes,
(SELECT COUNT(*) FROM Articles_Comment WHERE ArticleId=A.Id) AS Comments,
CASE WHEN EXISTS (SELECT Id FROM Articles_Like WHERE ArticleId=A.Id AND UserId=@UserId)
THEN 1 ELSE 0 END AS IsLiked,
CASE WHEN EXISTS (SELECT Id FROM Articles_Bookmark WHERE ArticleId=A.Id AND UserId=@UserId)
THEN 1 ELSE 0 END AS IsBookmarked
FROM Articles A
LEFT OUTER JOIN Articles_Info I ON I.ArticleId = A.Id
LEFT OUTER JOIN Users_Info U ON U.UserId = A.UserId
GROUP BY A.Title, A.BriefText, A.Id, I.ArticleView, U.DisplayName, U.Avatar, U.UserId
) dt
ORDER BY
CASE WHEN @orderby=1 THEN Id END DESC,
CASE WHEN @orderby=2 THEN ArticleView END DESC,
CASE WHEN @orderby=3 THEN Likes END DESC
我在存储过程的顶部使用了此代码,这不是使用代码两次的正确方法
对于过程语言来说确实如此,但不幸的是对于 SQL 来说,为了获得最佳结果有时确实需要重复复杂的表达式。一般来说,查询引擎足够聪明,不会重复工作,并且只会执行一次表达式,同时仍然在两个地方使用它。
同样,由于 SQL 足够智能,不会重复工作,因此您可能会重新考虑如何定义
IsLiked
列,因此它会重新使用相同的表达式,并在结果 > 0 时返回正确的值。