使用CASE时无法在列别名上进行ORDER BY

时间:2014-07-15 20:33:59

标签: sql sql-server stored-procedures

我的专栏会显示​​“活跃”字样。如果到期日期'在empTable中<当前日期,并将显示“无效”状态'否则,然后我想对该列进行排序,以便所有人都活跃起来'员工将处于最顶层。

CREATE PROCEDURE SOME_SP
@SortBy VARCHAR(10)
AS
SELECT emp.empname, 
CASE WHEN (emp.expiration_date < CURRENT_TIMESTAMP) THEN 'Active'   ELSE 'InActive' END AS Emp_Status, DeptName
FROM empTable emp, Dept dpt
WHERE emp.ID = dpt.ID
CASE @sortBy WHEN 'NAME' THEN emp.empName END,
CASE @sortBy WHEN 'STATUS' THEN Emp_Status END

如果用户输入&#39; NAME&#39;,则SP将按emp.empName排序,该工作正常,但不是状态

我收到错误消息,指出列名称无效&#39; Emp_Status&#39;

我做错了什么?

  

编辑:我很抱歉,我发现这个查询在纯SQL中是有效的。但是,事实是我在存储过程中执行此操作,用户可以在其中指定要排序的列。我将在上面发布一个更完整的SP。

1 个答案:

答案 0 :(得分:1)

好的,这里有一些评论。

1 - 请远离旧式连接。使用INNER JOIN ON子句。

2 - 没有理由不在ORDER BY子句中使用别名。请参阅Itzik Ben-Gans发布的逻辑处理订单。 SELECT参数在ORDER BY之前处理。

http://www.sql.co.il/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf

3 - 最后但并非最不重要的是,一个简单的例子(冒险工作),使每个人的雇用日期低于2004年为活跃,其他人都处于活跃状态。这将按状态列排序。

祝你好运。

约翰

-- Sample database
Use AdventureWorks2012
GO

-- Sample select showing alias works fine in a order by clause.
SELECT [LoginID] as login_id,
    CASE WHEN (e.HireDate < '20040101') THEN 'Active' 
    ELSE 'InActive' END AS emp_status
FROM [HumanResources].[Employee] as e
ORDER BY emp_status desc
GO

由于您更改了上面的代码,因此这是一个匹配的新答案。对于ORDER BY上的CASE语句,您必须使用实际列。对于一个简单的ORDER BY,别名将起作用。

所有答案都是答案!!

Use AdventureWorks2012
GO

ALTER PROCEDURE usp_Sort_By_Column(@sort varchar(25))
AS
SELECT 
    [LoginID] as login_id,
    CASE WHEN (e.HireDate < '20040101') 
    THEN 'Active' ELSE 'InActive' END AS emp_status
FROM 
    [HumanResources].[Employee] as e
ORDER BY 
   (CASE 
       WHEN @sort = 'ID' THEN [LoginID] ELSE 
        (CASE WHEN (e.HireDate < '20040101') 
        THEN 'Active' ELSE 'InActive' END)
     END) 
GO

usp_Sort_By_Column 'STATUS'

链接到ORDER BY - 在线图书......

http://msdn.microsoft.com/en-us/library/ms188385.aspx

疯狂查询的最佳答案:使用变量创建动态排序列。只需按第一列排序。最干净的答案。

Use AdventureWorks2012
GO

ALTER PROCEDURE usp_Sort_By_Column(@sort varchar(25))
AS
SELECT 
    (CASE 
       WHEN @sort = 'ID' THEN [LoginID] ELSE 
        (CASE WHEN (e.HireDate < '20040101') 
        THEN 'Active' ELSE 'InActive' END)
     END) as Sort_Column,

    [LoginID] as login_id,
    CASE WHEN (e.HireDate < '20040101') 
    THEN 'Active' ELSE 'InActive' END AS emp_status
FROM 
    [HumanResources].[Employee] as e
ORDER BY 
   1
GO

usp_Sort_By_Column 'ID'