SQL分批查询-UNION与UNIONALL使⽤技巧
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
sql中union多表合并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,
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
lumn_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,
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
lumn_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
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论