2013-03-20 64 views
2

的SQL Server 2005通過組別名

​​

我只是想爲每個CUSTID一行。相反,我得到:

CustID | Read | Write | Own | Destroy 

208345482  X  NULL NULL NULL| 
208345482 NULL NULL  X  NULL| 
208345482 NULL NULL NULL  X| 
208345482 NULL X  NUL NULL| 
8093657522 NULL NULL NULL  X| 
8093657522 NULL NULL  X NULL| 

我試圖通過別名子查詢分組無效。任何援助將不勝感激。

回答

3

您不能在GROUP BY中使用別名,因爲它在應用別名之前被解析。唯一可以使用別名的地方在ORDER BY子句中,因爲它是在定義了別名的SELECT之後解析的唯一子句。

典型的解決方法要麼重複表達GROUP BY子句中:

SELECT x = CASE ... END, SUM(something) 
    FROM dbo.somewhere 
    GROUP BY CASE ... END; 

,或者使用CTE:

;WITH src AS 
(
    SELECT x = CASE ... END, something 
    FROM dbo.somewhere 
) 
SELECT x, SUM(something) 
    FROM src 
    GROUP BY x; 

或者使用子查詢:

SELECT x, SUM(something) 
    FROM 
    (
    SELECT x = CASE ... END, something 
     FROM dbo.somewhere 
) AS src 
    GROUP BY x; 

這些都應該優化類似,但你應該測試你的具體情況,以確保。

在你的情況,你可以寫成如下這樣:

SELECT CustID, 
    [Read] = MAX(CASE permission WHEN 'read' THEN 'X' END), 
    [Write] = MAX(CASE permission WHEN 'write' THEN 'X' END), 
    [Own]  = MAX(CASE permission WHEN 'own'  THEN 'X' END), 
    [Destroy] = MAX(CASE permission WHEN 'destroy' THEN 'X' END) 
FROM dbo.rights 
GROUP BY custID; 

或者這樣:

SELECT CustID, 
    MAX([Read]), MAX([Write]), MAX([Own]), MAX([Destroy]) 
FROM 
(
    SELECT CustID, 
    [Read] = CASE permission WHEN 'read' THEN 'X' END, 
    [Write] = CASE permission WHEN 'write' THEN 'X' END, 
    [Own]  = CASE permission WHEN 'own'  THEN 'X' END, 
    [Destroy] = CASE permission WHEN 'destroy' THEN 'X' END 
    FROM dbo.rights 
) AS src 
GROUP BY custID; 

請不要使用單引號來分隔列或表'alias'。不僅是語法不贊成,而且它也使得實體看起來像一個字符串文字。如果必須轉義(例如,如果您選擇錯誤的列名稱),請使用[square brackets]

+0

「您不能在GROUP BY中使用別名,因爲它在應用別名之前被解析。」但是爲什麼在應用別名之前解析它? – 2013-10-24 11:03:54

+1

@anario我不知道我是否可以真正告訴你爲什麼,除了這是SQL Server的工作方式。 (我相信MySQL在這方面稍微寬鬆一點,但大多數真實平臺應該更貼近標準。)關於[這個問題]的更多細節(http://dba.stackexchange.com/questions/19762/爲什麼是選擇子句列出第一/)和[這個問題](http://dba.stackexchange.com/questions/21965/why-are-queries-parsed-in-such-a-way -that-disallows-the-use-of-column-aliases-in /)over dba.se. – 2013-10-24 13:20:50

+0

有用的鏈接,我現在滿意:) – 2013-10-24 13:55:53

0

您可以使用PIVOT表運算符在一個查詢中直接使用,而不是使用這些CASE表達式。

它將執行您正在尋找的更進一步的步驟,即使用CASE表達式將記錄分散之後的記錄分組。喜歡的東西:

SELECT 
    CustId, 
    read, 
    write, 
    own, 
    Destroy 
FROM 
( 
    SELECT custid, permission, x 
    FROM tablename 
) AS t 
PIVOT 
(
    MAX(x) 
    FOR permission IN('read', 
        'write', 
        'own', 
        'Destroy') 
) AS p; 

在您的查詢,如果x是一個字符串文字不是標識符,那麼你可以選擇它通常作爲一個字符串字面量在錨查詢SELECT custid, permission, 'x' AS x FROM tablename一個別名,然後上面的查詢應該正常工作。