1. 程式人生 > >MYSQL中子查詢有多個結果返回怎麼處理

MYSQL中子查詢有多個結果返回怎麼處理

問題
1. 查詢條件不一樣,返回多個結果整合
在查詢的時候,有時候經常需要用到子查詢,比如查詢今天的訂單數量, 7天的訂單數量,31天的訂單數量, 這種條件不一樣,但是非要整在一個表中來顯示就需要很多子查詢來實現了:

select(select xx from xx where 條件一) as 結果一,
select(select xx from xx where 條件二) as 結果二,
select(select xx from xx where 條件三) as 結果三


這個時候我們需要在一條sql將這三個結果查出來,可以使用UNION和UNION ALL

UNION 用於合併兩個或多個 SELECT 語句的結果集,並消去表中任何重複行。當 ALL 隨 UNION 一起使用時(即 UNION ALL),不消除重複行

也就是我們可以拼成一個表,比如現在有這麼一個表:


如果我們需要分別查出年齡小於18和大於18的人數,由於查詢條件不一樣,所以需要用到兩個查詢

SELECT 
  COUNT(*) 
FROM
  USER 
WHERE age < 18 ;

SELECT 
  COUNT(*) 
FROM
  USER 
WHERE age >= 18 ;


使用UNION:

SELECT 
  * 
FROM
  (SELECT 
    COUNT(*) 
  FROM
    USER 
  WHERE age < 18 
  UNION
  SELECT 
    COUNT(*) 
  FROM
    USER 
  WHERE age >= 18) a 


但是查出來的結果是在一列裡面,無法得知哪個是18以下的

我們可以拼接一個0使其為兩個欄位(兩列),這裡注意兩條子查詢的別名都要一樣

SELECT 
  * 
FROM
  (SELECT 
    COUNT(*) AS '18以下人數',
    0 AS '18以上人數' 
  FROM
    USER 
  WHERE age < 18 
  UNION
  SELECT 
    0 AS '18以下人數',
    COUNT(*) AS '18以上人數' 
  FROM
    USER 
  WHERE age >= 18) a 

這個時候是兩條記錄,分別使用SUM得到總數就可以變成一條記錄了

2. 查詢條件一樣,返回多個結果整合
但是有時候, 幾個結果的條件是一樣的, 但是子查詢只能返回一個結果, 也就是我們需要分成多個子查詢來查詢相同的條件

SELECT(SELECT xx FROM xx WHERE 條件一) AS 結果一,
SELECT(SELECT xx FROM xx WHERE 條件一) AS 結果二,
SELECT(SELECT xx FROM xx WHERE 條件一) AS 結果三,
SELECT(SELECT xx FROM xx WHERE 條件二) AS 結果四


處理
在網上搜羅一圈後, 有一個解決辦法挺新穎的, 大概就是先把同樣條件的多個結果, 先拼接成一個, 再在外面進行拆分, 在java裡面比如是"aa,bb,cc".split(",")

select 
SUBSTRING_INDEX(temp.結果一,',',1) as 第一列資料,
SUBSTRING_INDEX(SUBSTRING_INDEX(temp.結果一,','2),',',-1) as 第二列資料,
SUBSTRING_INDEX(temp.結果一,','-1) as 第三列資料,
temp.結果二 as 第四列資料
FROM(
    select(select concat_ws(',',資料一, 資料二,資料三)  from xx where 條件一) as 結果一,
    select(select xx from xx where 條件二) as 結果二
)temp



[補充]關於substring_index的用法
SUBSTRING_INDEX('待切割的字串', '擷取分割的字元,比如逗號' , 長度)
長度為負數,從右邊開始, 比如"a,b,c,d", 長度為-1取得是"d"(可以理解為在java中,利用split分割之後,取陣列中的前幾個元素)

取a: SUBSTRING_INDEX("a,b,c,d" , "," , 1)
取b: SUBSTRING_INDEX(SUBSTRING_INDEX("a,b,c,d" , "," , 2) ,",",-1) 先拿到前2位,再取最後一位
取d: SUBSTRING_INDEX("a,b,c,d" , "," , -1)
取cd: SUBSTRING_INDEX("a,b,c,d" , "," , -2)


示例1:

SELECT
    SUBSTRING_INDEX(temp.today, ",", 1) AS `今日加購量`,
    SUBSTRING_INDEX(temp.today, "," ,- 1) AS `今日加購商家數`
FROM
    (
        SELECT
            CONCAT_WS(
                ',',
                COUNT(*),
                COUNT(DISTINCT c.MALL_STORE_ID)
            ) AS today
        FROM
            mall_goods_cart c
        WHERE
            STR_TO_DATE(c.CREATE_TIME, '%Y-%m-%d') = CURDATE()
    ) AS temp

mysql日期函式函式:

SELECT NOW(),CURDATE(),CURTIME()
NOW() CURDATE() CURTIME()
2008-12-29 16:25:46 2008-12-29 16:25:46

 

示例2:需求:關聯查詢另一個大表資料的某些(一個以上)欄位

方案:因關聯查詢的表資料太大。多表查詢影響效率,單個子查詢又有些多餘。所以採用多列拼接子查詢,然後根據SUBSTRING_INDEX(SOURCE,SEPARETOR,INDEX+1)。

原理:子查詢返回拼接列;函式擷取還原列

SELECT
SUBSTRING_INDEX(temp.temp_column,",",1) showFirst,
SUBSTRING_INDEX(temp.temp_column,",",-1) showOver,
SUBSTRING_INDEX(SUBSTRING_INDEX(temp.temp_column,',',2),',',-1) showTwo,
temp.*
FROM
(
  SELECT (
  SELECT CONCAT_WS(',','12','23','34','45')) temp_column
) temp;

當然,如果僅僅只是在返回的多行資料之中隨便抽取一列即可,可以使用limit,,找到一個符合條件的就可以了

select * from table1 where table1.colums=(select columns from table2 limit 1);

或者使用any函式:

select * from table1 where table1.colums=any(select columns from table2);