SQL分批查詢-UNION與UNION ALL 使用技巧


  union和union all都用於合並sql結果集操作,不管sql語句是否相同,但是返回字段最好一樣,若不一樣,字段名稱只會以第一個為准

這就要求sql語句擁有相同的列(數量及名稱),相同的返回類型

首先說下區別:

  union 查詢結果不包含重復值,即若有重復只返回一個

  union all 查詢結果包含所有值,重復多少個都會全部返回

使用:使用多條件模糊(或者說篩選)查詢方法較慢(數據量較大)可換用另一種精確(索引或某字段)定位但sql過長的情況下、或者where條件中in過長(一般查過1000個會報錯)、或者sql語句過長的情況,可以考慮將其轉化為多個sql合並的union

  示例1:指定每個小條件的索引作為id值(對於各組條件並不是完全不同或可能有沒寫條件拆分到多個sql的情況),每個sql中限定查詢的成品個數,然后合並多個這樣的sql

      如下php中sql查詢代碼組織:

     $sql="";

     foreach
($productUuidArray as $index => $productArray) { $editStatus = $productArray['edit']; $uuids = implode(",", $productArray['uuid']); if($uuids=="") { //無成品信息,直接跳過 continue; } $sql .= "SELECT $index AS id,COUNT(DISTINCT product_uuid) AS dis_number,MAX(create_time) AS dis_time FROM log_info WHERE customer_id=$customerId AND edit_status=$editStatus AND product_uuid IN (" . $uuids . ") UNION "; }

      sql語句:

      SELECT $index AS id,COUNT(DISTINCT product_uuid) AS dis_number,MAX(create_time) AS dis_time
                FROM log_info
                WHERE customer_id=$customerId
                AND edit_status=$editStatus
                AND product_uuid IN (" . $uuids . ")
                UNION

       SELECT $index AS id,COUNT(DISTINCT product_uuid) AS dis_number,MAX(create_time) AS dis_time
                FROM log_info
                WHERE customer_id=$customerId
                AND edit_status=$editStatus
                AND product_uuid IN (" . $uuids . ")

      上述sql的條件為三個:customer_id、edit_status、product_uuid,其中關鍵在於product_uuid字段,若某一組customer_id與edit_status相同的sql中uuid個數多於1000個時,應拆分為另一sql,所以可能會將product_uuid拆分到兩個或更多的sql,customer_id及edit_status相同、product_uuid不同的情況,這時使用相同的$index作為索引,之后對查詢結果進行判斷組織(相同id的結果集:count相加、dis_time取最大的那個)即可

      此方法應注意合並后的sql長度,一般sql行數5000行以內是沒有問題的,大於5000行的情況,則應分多次查詢數據庫。極限的情況可能是每個in里只有一個uuid,這樣,每次查詢最多uuid為5000/6近似==800(一般取700以內)個,所以,組織$productUuidArray時,可以每0~700個查詢一次數據庫

  示例2:添加排序

       針對分批查詢的數據排序,不能在每個小sql中排序,但可以在最后集中排序,示例如下:

        

SELECT
    pi.channel_id,
    pi.column_id,
    pg.edit_status,
    pi.schema_id,
    pi.uuid,
    pi.play_start_time
FROM
    product_info pi
INNER JOIN product_progress_info pg ON pi.uuid = pg.product_uuid
WHERE
    pi.channel_id = 80
AND pi.column_id = 236
AND pg.edit_status = 1
AND pi.schema_id = 1
AND (
    (
        pi.play_start_time >= '2013-07-29 00:00:00'
        AND pi.play_start_time <= '2013-07-29 23:59:59'
    )
)
UNION
    SELECT
        pi.channel_id,
        pi.column_id,
        pg.edit_status,
        pi.schema_id,
        pi.uuid,
        pi.play_start_time
    FROM
        product_info pi
    INNER JOIN product_progress_info pg ON pi.uuid = pg.product_uuid
    WHERE
        pi.channel_id = 80
    AND pi.column_id = 10465
    AND pg.edit_status = 1
    AND pi.schema_id = 1
    AND pi.play_start_time >= '2013-07-29 00:00:00'
    AND pi.play_start_time <= '2013-07-29 23:59:59'
ORDER BY
        channel_id,
        column_id,
        edit_status,
        schema_id,
        play_start_time

 

    注:1.使用union的子sql不能包含排序語句

          2.排序的列名必須與第一個子sql的列名相同,保險起見,可以使用索引id,如上sql排序可寫:ORDER BY 1,2,3,4,6 ASC

        3.排序字段列名不能帶上表的別名,如channel_id不能寫作pi.channel_id

 

 

       

 

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM