2011-04-05 75 views
9

我的UPDATE語句的線沿線的雲:SQL - 使用CASE語句更新,是否需要多次重複相同的CASE?

UPDATE customer 
SET forenames=ot.forenames, 
    surname = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test SAFEPLACE IS NULL' 
ELSE 'test Safeplace IS NOT NULL' 
END, 

    middlename = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test2 SAFEPLACE IS NULL' 
ELSE 'test2 Safeplace IS NOT NULL' 
END, 

FROM order_transaction ot 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 

上述作品。它基本上檢查另一個表中的字段是否爲NULL,然後相應地更新客戶的「姓」和「中間名」。正如你在上面看到的,我重複了兩次相同的CASE陳述。我的問題是 - 有沒有一種方法可以只指定一次CASE語句?

重點是,如果我說要根據一定的條件更新10個字段,我是否需要包含10個相似的CASE條件?或者SQL可以改進爲只有一個CASE,並且WHEN/ELSE子句中有10個字段更新?

(我使用Postgresql 8.2數據庫,但我相信上面是標準的SQL)。

非常感謝, 仙人

回答

3

如果你想執行同一查詢級的情況下,你需要重複的情況下,就像你會重複計算列在group by子句中。

你的樣品查詢沒有顯示在所有你想做的事,你真的更新所有記錄相同的值(固定文字),以及每條記錄​​都列。如果您更新以使問題更相關,則可能有更好的答案。


但現在,對於您的具體問題,你可以使用類似這樣

UPDATE customer 
SET forenames=ot.forenames, 
    surname = fixedText, 
    middlename = fixedText  
FROM (select o.*, CASE 
     WHEN safeplace IS NULL 
     THEN 'test2 SAFEPLACE IS NULL' 
     ELSE 'test2 Safeplace IS NOT NULL' 
     END fixedText 
     from order_transaction o) ot 
WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
+0

不是最好的解決方案理查德。當您的選擇首先掃描表並添加結果,然後過濾它。 – 2011-04-05 08:26:59

+1

@Dumitrescu Bogdan /我不認爲它這樣做。因爲PostgreSQL將展開查詢以將過濾器應用到子查詢中,但仍保留使用定義(計算)列的能力。 – RichardTheKiwi 2011-04-05 08:33:40

+0

OP的語法不是標準SQL(也請注意,SQL標準是國際化的,而'A'是'ANSI'代表'美國',所以「符合ISO的SQL」在這裏更合適:) – onedaywhen 2011-04-05 09:06:15

0

如果您需要確切的情況下,多次複印(很多更然後2)你可以使用一個查詢。但是,你必須真的需要複製案件,而不是測試和測試2(這不完全相同的情況)。很明顯,如果你需要連接測試/測試2或其他任何文本到結果,那麼你可以在select語句中完成。例如:surname ='test'+ st.result,所以有一些可能做一些'黑客'。

UPDATE customer 
SET forenames=ot.forenames, 
    surname = st.result, 
    middlename = st.result 

FROM order_transaction ot 
JOIN (select 1 as ID,'test SAFEPLACE IS NULL' as result 
     union 
     select 2,'test SAFEPLACE IS NULL') st on case when ot.safeplace is null then 1 else 2 end = st.id 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
7

我相信上面是標準的SQL

其實,事實並非如此。標準SQL沒有UPDATE..FROM語法。相反,您需要爲每個SET子句加上另一個用於EXISTS的標量子查詢,因此標準語法更加重複,例如

UPDATE customer 
    SET forenames = (
        SELECT ot.forenames 
         FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ), 
     surname = (
        SELECT CASE 
          WHEN ot.safeplace IS NULL 
           THEN 'test SAFEPLACE IS NULL' 
          ELSE 'test Safeplace IS NOT NULL' 
         END 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
         AND ot.trans_orderid = 5678 
       ), 
     middlename = (
        SELECT CASE 
           WHEN ot.safeplace IS NULL 
            THEN 'test SAFEPLACE IS NULL' 
           ELSE 'test Safeplace IS NOT NULL' 
          END 
         FROM order_transaction AS ot 
         WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ) 
WHERE customer.custid = 1234 
     AND EXISTS (
        SELECT * 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
       ); 

雖然語法看起來重複,一個好的優化應該能夠識別重複並據此進行優化。當前版本的SQL產品是否確實在實踐中優化了這一點當然是另一回事。但請考慮一下:如果您選擇的SQL產品支持標準語法,但實際上並沒有對其進行正確優化,那麼「支持」值得什麼?

如果您正在尋找使用標準SQL(您確實應該使用IMO :),並且需要更緊湊的語法,請參閱MERGEMERGE (SQL)可能看起來更像這樣:

MERGE INTO customer 
    USING (
      SELECT ot.custid, ot.forenames, 
       CASE 
        WHEN ot.safeplace IS NULL 
         THEN 'test SAFEPLACE IS NULL' 
        ELSE 'test Safeplace IS NOT NULL' 
        END 
      FROM order_transaction AS ot 
      WHERE ot.trans_orderid = 5678 
     ) AS source (custid, forenames, safeplace_narrative) 
    ON customer.custid = source.custid 
     AND customer.custid = 1234 
WHEN MATCHED THEN 
    UPDATE 
     SET forenames = source.forenames, 
      surname = source.safeplace_narrative, 
      middlename = source.safeplace_narrative; 
+0

@Richard又名cyberkiwi:更新了答案以添加MERGE示例以顯示它更緊湊同時保留標準SQL。 – onedaywhen 2011-04-11 10:25:27