聚集字段排序

实在不知道为该篇文章起个标题。大概的场景是,窗口的聚集运算等。因为,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) 这四个字段值相等。

缺点是:可能出现重复。貌似性能也不会很高。

再去重等。