1. 程式人生 > >Mysql之case基本用法

Mysql之case基本用法

MySQL 的 case when 的語法有兩種:

      1.簡單函式 (比較col_name和when後面的值是否相等)

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END

 

     2.搜尋函式 (判斷when後面的表示式expr是否為true,如果為true,則返回result1)

CASE WHEN [expr] THEN [result1]…ELSE [default] END

兩種語法的區別

簡單函式

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END: 列舉這個欄位所有可能的值
SELECT
    NAME '樹名',
    CASE NAME
        WHEN '桃樹' THEN
            '桃花'
        WHEN '梨樹' THEN
            '梨花'
        WHEN '芙蓉' THEN
	    '蓮花'	
        ELSE
            '無名花'
    END '花名'
FROM
    tree_info;

查詢結果:

搜尋函式

CASE WHEN [expr] THEN [result1]…ELSE [default] END:搜尋函式可以寫判斷,並且搜尋函式只會返回第一個符合條件的值,其他case

被忽略

SELECT
    age '年齡段',
    CASE
        WHEN age <= 10 THEN
            '不愁'
        WHEN age <= 20 THEN
            '不悔'
        WHEN age <= 30 THEN
            '而立'
        WHEN age <= 40 THEN
            '不惑'
        WHEN age <= 50 THEN
            '知天命'
        WHEN age <= 60 THEN
            '耳順'
        ELSE
            '年級大了'
    END '狀態'
FROM
    age_info;

查詢結果:

特殊用法

1.聚合函式 sum 配合 case when 的簡單函式實現行轉列

表1:courses

表2:score

表3:student:

測試:

SELECT
    st.stu_id '學號',
    st.stu_name '姓名',
    SUM(
        CASE co.course_name
        WHEN '語文' THEN
            sc.scores
        ELSE
            0
        END
    ) '語文',
    SUM(
        CASE co.course_name
        WHEN '數學' THEN
            sc.scores
        ELSE
            0
        END
    ) '數學',
    SUM(
        CASE co.course_name
        WHEN '物理' THEN
            sc.scores
        ELSE
            0
        END
    ) '物理',
    SUM(
        CASE co.course_name
        WHEN '化學' THEN
            sc.scores
        ELSE
            0
        END
    ) '化學',
    SUM(
        CASE co.course_name
        WHEN '生物' THEN
            sc.scores
        ELSE
            0
        END
    ) '生物',
    SUM(
        CASE co.course_name
        WHEN '歷史' THEN
            sc.scores
        ELSE
            0
        END
    ) '歷史'
FROM
    student st
LEFT JOIN score sc ON st.stu_id = sc.stu_id
LEFT JOIN courses co ON co.course_no = sc.course_no
GROUP BY
    st.stu_id
ORDER BY
    NULL;

測試結果:

一般我們查詢的時候,根據stu_id分組,例如:

SELECT
    st.stu_id '學號',
    st.stu_name '姓名',
    GROUP_CONCAT(sc.scores),GROUP_CONCAT(sc.`course_no`),GROUP_CONCAT(co.`course_name`)
FROM
    student st
LEFT JOIN score sc ON st.stu_id = sc.stu_id
LEFT JOIN courses co ON co.course_no = sc.course_no
GROUP BY
    st.stu_id
ORDER BY
    NULL;

查詢結果:

這樣的查詢結果並不如例如case when 的行轉列資料清晰

2.把一行拆分為多了的示例

SELECT SipAccount, COUNT(1) AS number,IsCheck
FROM cdr
GROUP BY SipAccount,IsCheck

針對這個統計結果進行拆分(0表示未打分,1代表優秀,2代表合格,3代表不合格)

想要的最終結果如下:

所以最終要用到行拆分成三列,語句如下

SELECT SipAccount,
              (CASE IsCheck WHEN 1 THEN number END) youxiu,
              (CASE IsCheck WHEN 2 THEN number END) hege,
              (CASE IsCheck WHEN 3 THEN number END) buhege
 FROM
          (SELECT SipAccount, COUNT(1) AS number,IsCheck
           FROM cdr
           GROUP BY SipAccount,IsCheck) AS a

現在結果是這樣的,你會發現雖然拆成了三列,但是最終結果還不是自己需要的,接下來就需要根據sipaccount來分組的同時對結果進行處理了。語句如下:

SELECT sipaccount,
        IF(MAX(youxiu) IS NULL,0, MAX(youxiu)) youxiu,
        IF(MAX(hege) IS NULL,0, MAX(hege)) hege,
        IF(MAX(buhege) IS NULL,0, MAX(buhege)) buhege
FROM
        (SELECT SipAccount,
        (CASE IsCheck WHEN 1 THEN number END) youxiu,
        (CASE IsCheck WHEN 2 THEN number END) hege,
        (CASE IsCheck WHEN 3 THEN number END) buhege
        FROM
     (SELECT SipAccount, COUNT(1) AS number,IsCheck  FROM cdr  GROUP BY SipAccount,IsCheck) AS a) AS b
                    GROUP BY sipaccount

最終得到了這個結果。正式我們需要的格式

MySQL的IF函式(返回兩個不同結果的時候用IF,如果返回多個不同的結果,用case when)

格式:IF(Condition,A,B)

意義:當Condition為TRUE時,返回A;當Condition為FALSE時,返回B。

3.mysql 使用Case When 達到排序的效果

SELECT DISTINCT dev.deviceId, dev.deviceTypeCode, dev.mcuID, dev.workState, dtf.dcTypeCode from devicebase dev
 ORDER BY 
  CASE dev.workstate
  WHEN '3' THEN 0
  WHEN '2' THEN 1
  WHEN 'x' THEN 2
  WHEN 'y' THEN 3
  WHEN '1' THEN 4
  ELSE 5 END,  dev.workstate

或者

SELECT DISTINCT dev.deviceId, dev.deviceTypeCode, dev.mcuID, dev.workState, dtf.dcTypeCode,
	CASE dev.workstate
 	WHEN '3' THEN 0
 	WHEN '2' THEN 1
 	WHEN 'x' THEN 2
 	WHEN 'y' THEN 3
 	WHEN '1' THEN 4
 	ELSE 5 END 
	AS state
 from devicebase dev
 ORDER BY state

4.利用case when實現分組(在網上搜索case when的時候找到的其他示例)

1-4級為一組,5,6級為一組,5-6級的優先處理,之後在處理1-4級

SELECT * FROM t_automatic_assign t ORDER BY t.RETRIEVE_STATUS DESC,
CASE WHEN DECISION_LEVEL = 5 OR DECISION_LEVEL = 6 THEN 1
ELSE 2 END t.CREATE_DATE ASC

5.利用case when實現細化分組

使用者查詢兩個狀態的列表,進行排序, 然後在第一個狀態和第二個狀態時按照lastLoginDate降序在第三個狀態按照tokencreatetime升序

SELECT * FROM yun_user WHERE type IN(2,1,99) ORDER BY type ASC,
CASE WHEN type = 2 OR type=1 THEN lastLoginDate END DESC,
CASE WHEN type=99 THEN  tokencreatetime END ASC;

6.摘自其他部落格的一個例項

條件:某欄位代表該資料的狀態取值為非負整數,0表示無狀態。

  需求:以該欄位升序排序,同時需要將值為0的資料放在最後。

  首先我們看一下,表的結構:

  

 

  正常的使用升序查詢結果是這樣的:

  

 

  要讓“小赤”排在最後,可以這樣寫:

  

 

  也可以這樣:(mysql的除數為0,則值為null,不會報錯)

  

 

  還可以使用 CASE WHEN 再不影響查詢結果的前提下,改變排序的依據:

  

7.case when 返回的應該是一個字串型別的,而不是實際的那個變數的值的型別,例如有表結構

score表中,scores的屬性型別為float,數值如下:

按照分數scores排序:

SELECT * FROM `score` ORDER BY `scores`

利用case when排序,以為case when的條件為false,所以實際上也是按照scores排序,但是和order by scores排序的結果集順序不一致,如下圖:

如果想使用case when 並且按照數字大小排序可以這麼做,在case when 的返回值後面+0,即主動把case when的返回值變為數字型別:

case when的用法就總結到這裡,如果有不對