slim|lumen|laravel 【組合查詢 union】
一。基礎概念解釋
定義:
在大多數開發中,使用一條SELECT查詢就會返回一個結果集。如果,我們想一次性查詢多條SQL語句,並將每一條SELECT查詢的結果合併成一個結果集返回。就需要用到Union操作符,將多個SELECT語句組合起來,這種查詢被稱為並(Union)或者複合查詢。
另外,在單表中使用Union比where多條件查詢較為複雜。而從多張表中獲取資料,使用Union會相對於簡單些。
組合查詢適用於下面兩種情境中:
從多個表中查詢出相似結構的資料,並且返回一個結果集
從單個表中多次SELECT查詢,將結果合併成一個結果集返回。
Union使用規則
Union有他的強大之處,詳細介紹之前,首先明確一下Union的使用注意規則。
Union必須由兩條或者兩條以上的SELECT語句組成,語句之間使用Union連結。
Union中的每個查詢必須包含相同的列、表示式或者聚合函式,他們出現的順序可以不一致(這裡指查詢欄位相同,表不一定一樣)
列的資料型別必須相容,相容的含義是必須是資料庫可以隱含的轉換他們的型別
包含重複、去除重複
union中mysql在查詢結果集中幫我們自動去除了重複的行(重複的行是李四),把兩條李四合並了。
select user_id,user_nickname,user_status from yy_user where user_status = 1 UNION select user_id,user_nickname,user_status from yy_user where user_id > 3
一般情況下這樣結果是好的,但是如果需要的情況下,我們可以使用Union All操作符來取消自動合併功能。
select user_id,user_nickname,user_status from yy_user where user_status = 1
UNION ALL
select user_id,user_nickname,user_status from yy_user where user_id > 3
結果排序
注意:由於在多表組合查詢時候,可能表字段並不相同。所以,在對於結果集排序的時候需要使用檢索出來的共同欄位。
(select user_id,user_nickname,user_status from yy_user where user_status = 1) UNION ALL (select user_id,user_nickname,user_status from yy_user where user_id > 3) order by user_id desc **上面檢索的欄位user_id必須存在於結果集中。**
多表組合查詢
大型專案中資料經常分佈在不同的表,檢索的時候需要組合查詢出來。多表查詢的時候,並不要求兩個表完全相同,只需要你檢索的欄位結構相似就可以。
select posts_id,posts_name,posts_status from yy_posts
UNION
select user_id,user_nickname,user_status from yy_user
區分多表
上一個例子中,我們組合查詢了user表和posts表。雖然結果混合在一起沒有任何問題,但是當顯示到頁面的時候,我們需要給使用者和文章不同的連結或者其他的區分。所以我們必須確定該條記錄來自於哪張表,我們可以新增一個別名來作為表名。
select posts_id,posts_name,posts_status,'users' as table_name from yy_posts
UNION
select user_id,user_nickname,user_status,'posts' as table_name from yy_user
注意SQL語句中的'users' as table_name。對應的是圖片裡的table_name,就是我們剛剛新增用於區別表的欄位。
二。專案中的實際應用
$db = $this->db;
$params = $request->getQueryParams();
$coupon = $db::table("coupon as c")
->select('c.id','c.coupon_head','c.min_money','c.max_money','c.coupon_type','c.allow_use_client',
'c.new_old_user','c.stock','c.start_time','c.end_time','c.created_time','c.coupon_type_text',
$db::raw("if(time_type='2',TIMESTAMPDIFF(day,date(c.created_time),c.start_time),'') as effective_time"),
$db::raw("if(time_type='2',TIMESTAMPDIFF(day,c.start_time,c.end_time),'') as finish_time"),
$db::raw("if(time_type='2','領取後n天有效,有效期x天',concat(c.start_time,'~',c.end_time))as time"),
$db::raw("concat(min_money,'~',max_money) as money"),
$db::raw("if(c.stock='0','不限制',stock) as stock_name"),
$db::raw("if(c.city_name='0','全國',city_name) as city"))
->where('c.is_delete','0');
$model = $db::table("delivery_coupon as cc")
->select('cc.id','cc.coupon_head','cc.min_money','cc.max_money','cc.coupon_type','cc.allow_use_client',
'cc.new_old_user','cc.stock','cc.start_time','cc.end_time','cc.created_time','cc.coupon_type_text',
$db::raw("if(cc.time_type='2',TIMESTAMPDIFF(day,date(cc.created_time),cc.start_time),'') as effective_time"),
$db::raw("if(cc.time_type='2',TIMESTAMPDIFF(day,cc.start_time,cc.end_time),'') as finish_time"),
$db::raw("if(cc.time_type='2','領取後n天有效,有效期x天',concat(cc.start_time,'~',cc.end_time))as time"),
$db::raw("concat(cc.min_money,'~',cc.max_money) as money"),
$db::raw("if(cc.stock='0','不限制',stock) as stock_name"),
$db::raw("if(cc.city_name='0','全國',city_name) as city"))
->where('cc.is_delete','0')
->unionAll($coupon)
->orderBy('created_time','desc');
$count = $db::selectOne("select count(*) as count_all from (" . $model->toSql() . ") as `count_all`",$model->getBindings())->count_all;
$coupon_all = $model
->skip(($params['page'] - 1) * $params['size'])->take($params['size'])
->get();
注意:
使用union all之後的sql語句類似於:
SELECT id FROM coupon UNION ALL SELECT id FROM delivery_coupon order by 'created_time','desc';
查詢聯查之後中的資料量:
select count(*) from (SELECT id FROM coupon UNION ALL SELECT id FROM delivery_coupon order by 'created_time','desc') as count;