导航
1、sql关键字执行的优先级
首先在我们了解这个排序错误之前我们需要基本了解sql关键字执行的优先级
关键字 | 优先级 |
---|---|
join | 1 |
where | 2 |
group by | 3 |
having | 4 |
order by | 5 |
limit | 6 |
而union 是个奇葩,正好夹在having和order by之间,要算的话可以算个4.5吧
按照这个表格看下来,我们就可以举个例子
select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from jinhuan_sales_order
where supervise ='已送审'
group by order_number
union all
select
'采购订单审批' as order_type,
'待审批' as status,
o.order_number,
o.supplier_name,
o.make_person,
o.for_review_date,
d.total_price,
o.currency,
o.audit_date
from table1 o
left join (select main_code,sum(tax_money) total_price from table2 group by main_code
) d on d.main_code = o.order_number
where o.supervise = '已送审'
group by order_number
--得出结果
销售订单审批 待审批 XSDD20230609001 xx 陆雪 2023-06-09 19050.00 2023-06-16
销售订单审批 待审批 XSDD20230609002 xxx 2023-06-09 33750.00 2023-06-16
销售订单审批 待审批 XSDD20230610003 xxxxx 管理员 2023-06-10 200000.00 2023-06-16
采购订单审批 待审批 CGDD20230610004 xxxxxx 管理员 2023-06-11 40000.000 人民币
--而我们将里面分组的内容改为order by时就会报一个错误
-- > 1221 - Incorrect usage of UNION and ORDER BY
2、解决方案
2.1 一条语句只使用一个order by,在最后使用
select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from jinhuan_sales_order
where supervise ='已送审'
union all
select
'采购订单审批' as order_type,
'待审批' as status,
o.order_number,
o.supplier_name,
o.make_person,
o.for_review_date,
d.total_price,
o.currency,
o.audit_date
from table1 o
left join (select main_code,sum(tax_money) total_price from table2 group by main_code
) d on d.main_code = o.order_number
where o.supervise = '已送审'
order by order_number
2.2 使用括号将他们包裹,让他们独自执行(能运行,结果不对)
(select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
order by for_review_date desc)
union all
(select
'采购订单审批' as order_type,
'待审批' as status,
o.order_number,
o.supplier_name,
o.make_person,
o.for_review_date,
d.total_price,
o.currency,
o.audit_date
from table o
left join (select main_code,sum(tax_money) total_price from table1 group by main_code
) d on d.main_code = o.order_number
where o.supervise = '已送审'
order by for_review_date desc)
3、更复杂的情况
当上下两条sql的排序字段不同时,可能还是会出现问题,例如
(select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
order by for_review_date desc
)
union all
( select
'销售订单审批' as order_type,
supervise as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where (supervise ='审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
order by audit_date desc )
# 查询结果
可见不管是未审批的单据还是审批通过的单据都没有按照希望的方向排序,这种情况是排序直接被mysql优化掉了
3.1 使用limit强行执行
(select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
order by for_review_date desc
limit 999)
union all
( select
'销售订单审批' as order_type,
supervise as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where (supervise ='审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
order by audit_date desc
limit 999)
结果如下:
两个分开的sql按照我们希望的结果完成拼接
3.2、自己试出来的(不一定能100%正确)
select
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
union all
select
'采购订单审批' as order_type,
'待审批' as status,
o.order_number,
o.supplier_name,
o.make_person,
o.for_review_date,
d.total_price,
o.currency,
o.audit_date
from table o
left join (select main_code,sum(tax_money) total_price from table1 group by main_code
) d on d.main_code = o.order_number
where o.supervise = '已送审'
union all
select
'盘点结果审批' as order_type,
'待审批' as status,
counting_code,
'公司' as supplier_name,
make_person,
for_review_date,
'' total_price,
'' currency,
approval_date as audit_date
from table
where approval_status = 2
order by for_review_date desc
) t
union all
select
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
supervise as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where (supervise ='审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
union all
select
'采购订单审批' as order_type,
supervise as status,
order_number,
supplier_name,
make_person,
for_review_date,
d.total_price,
o.currency,
o.audit_date
from table o
left join (select main_code,sum(tax_money) total_price from table1 group by main_code
) d on d.main_code = o.order_number
where (supervise = '审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
union all
select
'盘点结果审批' as order_type,
'审核通过' as status,
counting_code,
'公司' as supplier_name,
make_person,
for_review_date,
'' total_price,
'' currency,
approval_date as audit_date
from table
where approval_status = 1
and datediff(current_date(),for_review_date) <=7
order by audit_date desc
) t
得出结果:
结果居然也是正确的,不过但是发现把单一个提出来就有问题
select
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
order by for_review_date desc
)t
union all
select
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
supervise as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where (supervise ='审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
order by audit_date desc
) t
发现顺序还是不对。。所以就很奇怪我上面那一长串为什么会生效
3.3 最终解决方案
现在再一想,既然待审批的单子只需要送审时间,而审批通过的单子只需要审批时间,那么吧这两个字段结合到一起不就完事了,然后再通过自己设一个flag优先进行状态的排序
select
2 flag,
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
'待审批' as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
for_review_date,
total_price,
currency,
audit_date
from table
where supervise ='已送审'
)t
union all
select
1 flag,
t.order_type,
t.status,
t.order_number,
t.supplier_name,
t.make_person,
t.for_review_date,
t.total_price,
t.currency,
t.audit_date
from(
select
'销售订单审批' as order_type,
supervise as status,
sa_orderno as order_number,
cust_shortname as supplier_name,
makerman as make_person,
audit_date for_review_date,
total_price,
currency,
audit_date
from table
where (supervise ='审核通过' or supervise ='审核拒绝')
and datediff(current_date(),audit_date) <=7
) t
order by flag desc,for_review_date desc
可以得出最后排序正确
4、结论
1、在排序字段是同一个的情况下使用在最后使用order by是可以的
2、在排序字段不是同一个情况下使用limit可以达成自己想要的结论,但是不适合用于代码中
3、可以通过将两个字段合并成一个新的字段进行排序
版权声明:本文为weixin_52796198原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。