mysql使用union all导致排序错误

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

在这里插入图片描述
发现顺序还是不对。。所以就很奇怪我上面那一长串为什么会生效

扫描二维码关注公众号,回复: 16954125 查看本文章

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、可以通过将两个字段合并成一个新的字段进行排序

猜你喜欢

转载自blog.csdn.net/weixin_52796198/article/details/131303999