navigation
1. Priority of sql keyword execution
First, before we understand this sorting error, we need to have a basic understanding of the priority of SQL keyword execution.
Keywords | priority |
---|---|
join | 1 |
where | 2 |
group by | 3 |
having | 4 |
order by | 5 |
limit | 6 |
And union is a weird thing, it happens to be sandwiched between having and order by. If you want to calculate it, it can be calculated as 4.5.
Looking at this table, we can give an example
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. Solution
2.1 Only one order by is used in a statement, and it is used at the end
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 Wrap them in parentheses and let them execute alone (it works, but the result is wrong)
(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. More complex situations
When the sort fields of the upper and lower SQLs are different, problems may still occur, for example
(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 )
# 查询结果
It can be seen that neither the unapproved documents nor the approved documents are sorted in the desired direction. In this case, the sorting is directly optimized by MySQL.
3.1 Use limit to force execution
(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)
The result is as follows:
two separate sql are spliced according to the result we want.
3.2. Tried by myself (may not be 100% correct)
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
The result is obtained:
The result is actually correct, but I found that there is a problem in bringing up a single one.
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
I found that the order was still wrong. . So it’s very strange why the long list above me takes effect.
3.3 Final solution
Now think about it again, since the orders to be approved only need the submission time, and the approved orders only need the approval time, then it is enough to combine these two fields, and then set a flag to prioritize the status. sort
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
It can be concluded that the final sorting is correct
4 Conclusion
1. It is okay to use order by at the end when the sorting fields are the same.
2. When the sorting fields are not the same, you can use limit to achieve the conclusion you want, but it is not suitable for use in code.
3. It is okay. Sort by merging two fields into a new field