聚集字段排序
实在不知道为该篇文章起个标题。大概的场景是,窗口的聚集运算等。因为,mysql5.7中并没有窗口函数,要进行适配。本文的内容:
可以看成:数据按一定条件去重。
可以看成:array_concat(字段 order by 其他字段),等等等。
也可以看成:我们知道,聚集运算的时候,不参与聚集运算的字段,是不能选择的,除非是使用了聚集函数,才能参与select。聚集函数执行后,使无法再查看原始数据的细节。本文,大概使用几种方式。
sql真的是非常灵活,同样一个需求,可能有n种表达方式。
原始sql
SELECT
CONCAT (K, ',', v) AS f
FROM
(
SELECT
branch_code * 1000000 + salesman_id AS k,
CONCAT (
branch_code,
'-',
delivery_code
),
row_number () over (
PARTITION BY branch_code,salesman_id
ORDER BY
create_time,update_time DESC
) AS rn
FROM
ydserver.ydwr_base_salesman_sorting
WHERE
delivery_code IS NOT NULL
) t
WHERE
t.rn = 1
因为,mysql5.7中并没有窗口函数,要进行适配。
使用max来计算
SELECT SUBSTR(max_value,39) from (
SELECT
branch_code,
salesman_id,
delivery_code,
max(CONCAT('hello',branch_code)),
branch_code * 1000000 + salesman_id,
concat(branch_code,'-',delivery_code),
create_time,
update_time,
max(CONCAT(
case when create_time is not null then create_time else '0001-01-01 00:00:00' end ,
case when update_time is not null then update_time else '0001-01-01 00:00:00' end ,
branch_code * 1000000 + salesman_id,',',branch_code,'-',delivery_code)
) as max_value
FROM
ydwr_base_salesman_sorting
GROUP BY branch_code,salesman_id
) t
缺点
如果有多个排序选择条件时,要么都选择最大、或者都选择最小,如果大小不一样,在字符串排序的时候,可能不好处理。
变通的方式,如时间,
3000-12-21 00:00:00 - 时间,使大小值发现转变。但是,使sql非常的复杂。
使用select 子查询
能比较好的实现各种的排序需求,但是确定时,貌似,只能选择出一个字段。多字段如何做呢?难道使用concat后再自己拆开吗?当然这也是一种思路,貌似合并字段,也是一种思路
思路来源:
如果只有1条,那么完全能使用一个查询查询。但是多条嘛,不就是额外加个,select子查询呗。
-- 采用子查询方式
SELECT
-- branch_code,salesman_id,
(select
CONCAT( branch_code * 1000000 + salesman_id,',',branch_code,'-',delivery_code)
from ydwr_base_salesman_sorting where branch_code = a.branch_code and salesman_id = a.salesman_id order by create_time,update_time desc limit 1
) as f
FROM
ydwr_base_salesman_sorting a
WHERE delivery_code is not null
GROUP BY branch_code,salesman_id
这种是比较适当的方式。理解起来比较简单,而且来满足各种排序的需求。
使用set变量
没有验证,使用变量来模拟窗口的row_number函数。
参考:https://www.cnblogs.com/starzy/p/11146156.html
SET @row=0;
SET @branch_c=0;
SET @salesman_i='';
select concat(r.k, ',', r.v) as f
from (
select
branch_code * 1000000 + salesman_id AS k,
CONCAT( branch_code, '-', delivery_code ) AS v
from (
select branch_code,salesman_id,delivery_code,
CASE WHEN @branch_c = branch_code and @salesman_i = salesman_id then
@row := @row + 1 else @row := 1 end rn,
@branch_c := branch_code,@salesman_i := salesman_id
from ydserver.ydwr_base_salesman_sorting
WHERE delivery_code IS NOT NULL
order by branch_code desc,salesman_id desc,create_time desc,update_time desc
) t
where t.rn = 1
order by branch_code desc,salesman_id desc,create_time desc,update_time desc
) r
其他思路
先分组查询,即查出:
branch_code,salesman_id,max(create_time),min(update_time) -- 这四个字段。
然后,再根据上面的四个条件,作为联表的查询值。
select * from table left join on
branch_code,salesman_id,max(create_time),min(update_time) 这四个字段值相等。
缺点是:可能出现重复。貌似性能也不会很高。
再去重等。