【问题标题】:sorting via order by and row_number via user variable in mariadb通过 mariadb 中的用户变量通过 order by 和 row_number 排序
【发布时间】:2015-05-11 20:34:20
【问题描述】:

我已经读到,操作的任何顺序都是在查询结束时完成的,因此之前不能在结果中强制排序。

所以我想要实现的是通过使用分配行号的变量和使用从句我只选择第一行来从重复的结果中获取一条记录。

对不起,我的解释不好,我希望你看看我的意思:

select *
from address left join
(select address.add_nr as add_nr, acc.typ as typ, acc.seq as seq,
@num := if(@add_nr = address.add_nr, @num + 1, 1) as row_number,  
@add_nr := address.add_nr as dummy
from 
address left join


(

select con_add_nr as add_nr, 'XY' as typ, 1 as seq
from conctract,conctractdet
where con_pol_kz IN('L')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
group by 1,2,3

union
select ris_add_nr as add_nr, 'XX' as typ, 4 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and con_nr=ris_con_nr
and ris_art='VP'
group by 1,2,3


union
select ris_add_nr as add_nr, 'YY' as typ, 3 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and vrs_nr=ris_vrs_nr
and ris_art='VP'
group by 1,2,3


union
select ris_add_nr as add_nr, 'YX' as typ, 5 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and con_nr=ris_con_nr
and ris_art='2. VN'
group by 1,2,3


union
select ris_add_nr as add_nr, 'X' as typ, 2 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and vrs_nr=ris_vrs_nr
and ris_art='2. VN'
group by 1,2,3

order by add_nr,seq asc) as acc on acc.add_nr=address.add_nr
having row_number=1) as acc on address.add_nr=acc.add_nr;

所以问题是,当 row_number 已经被假定时,操作的顺序是在最后完成的。我需要的是首先按序列号“seq”对结果进行排序,实现第一个条目获取row_number = 1。目前“未排序”结果中的第一个条目获得 row_number=1,这不是我需要的。

【问题讨论】:

  • 请改写为JOIN...ON

标签: mysql variables sql-order-by mariadb temp-tables


【解决方案1】:

不要将HAVING 用于您通过用户变量动态生成的列。 MySQL 执行了一些优化,这搞砸了。相反,请在外部查询中使用 WHERE 子句。

select *
from address left join
(select address.add_nr as add_nr, acc.typ as typ, acc.seq as seq,
@num := if(@add_nr = address.add_nr, @num + 1, 1) as row_number,  
@add_nr := address.add_nr as dummy
from 
address 
cross join (select @add_nr := 0, @num := 0) AS init
left join


(

select con_add_nr as add_nr, 'XY' as typ, 1 as seq
from conctract,conctractdet
where con_pol_kz IN('L')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
group by 1,2,3

union
select ris_add_nr as add_nr, 'XX' as typ, 4 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and con_nr=ris_con_nr
and ris_art='VP'
group by 1,2,3


union
select ris_add_nr as add_nr, 'YY' as typ, 3 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and vrs_nr=ris_vrs_nr
and ris_art='VP'
group by 1,2,3


union
select ris_add_nr as add_nr, 'YX' as typ, 5 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and con_nr=ris_con_nr
and ris_art='2. VN'
group by 1,2,3


union
select ris_add_nr as add_nr, 'X' as typ, 2 as seq
from conctract,conctractdet,risaddress
where con_pol_kz IN('P','PU','A')
and con_nr=vrs_con_nr
and cond_spa_nr IN (102,160,173)
and vrs_nr=ris_vrs_nr
and ris_art='2. VN'
group by 1,2,3

order by add_nr,seq asc) as acc on acc.add_nr=address.add_nr) as acc on address.add_nr=acc.add_nr
WHERE row_number = 1;

documentation 中简要提到了此优化

如果您不使用GROUP BY 或聚合函数(COUNT()MIN() 等),HAVING 将与WHERE 合并。

这意味着如果它可以像对待WHERE 一样对待HAVING 子句,它就会这样做,因此它会在生成结果集时从结果中删除行,而不是等到所有结果行都生成后.

【讨论】:

  • 似乎每个选择上的GROUP BY 完全没用。 ??
  • 它可以简化为group by add_nr,因为typseq 在联合中的每个子查询中都是相同的。我们对数据知之甚少,无法判断是否需要这样做。
  • 非常感谢,现在结果是正确的。有什么地方可以让我了解更多关于优化的信息吗?仅供参考:需要 group by 否则我会从联合块中的每个查询中获得多行。
  • 我不确定它的记录是否完​​好,只是我在尝试使用它时发现的。
  • 我在手册中找到了一些关于它的内容,我已将其添加到答案中。
猜你喜欢
  • 2021-04-06
  • 2023-03-10
  • 1970-01-01
  • 2017-10-21
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多