MySQL查询从最新观察返回第n个滞后

时间:2018-07-05 15:06:50

标签: mysql sql

我有以下MySQL表:

function findSame(pos, sortedArr){
	for(let i =pos; i<sortedArr.length; i++){
		if(sortedArr[i] !== sortedArr[pos]){
			return i
		}
	}
}

function clubSameNumbers(unsortedArr){
	let sortedArr = unsortedArr.sort((a,b)=>a-b) 
	//[ 1, 1, 1, 1, 2, 2, 2, 4, 5, 10, 20, 20, 391, 392, 591 ]
	let result = []	
	for(let i = 0; i < sortedArr.length; i = end){
		let start = i
		var end = findSame(i, sortedArr)
		let arr = sortedArr.slice(i, end)
		arr.length > 1 ? result.push(arr) : result.push(...arr)    		
	}
	return result
}


console.log(clubSameNumbers([1,2,4,591,392,391,2,5,10,2,1,1,1,20,20]))
//[ [ 1, 1, 1, 1 ], [ 2, 2, 2 ], 4, 5, 10, [ 20, 20 ], 391, 392, 591 ]

我正在尝试编写MySQL查询,该查询将为每个组(公司)返回上次观察(销售)或距上次观察的第n个滞后。

我发现MySQL查询返回每个组的最后观察结果:

firm | Sales | year
A    | 100   | 2018
A    | 200   | 2017
A    | 300   | 2016
B    | 400   | 2017
B    | 500   | 2016
B    | 600   | 2015
C    | 700   | 2016
C    | 800   | 2015
C    | 900   | 2014

但是我不知道如何修改代码以返回最近观察到的滞后值,即:

select * 
from (select * from mytable order by `Group`, firm, datum desc) x
group by `Group`

2 个答案:

答案 0 :(得分:2)

我认为最通用的方法是使用变量枚举值:

select t.*
from (select t.*,
             (@rn := if(@f = t.firm, @rn + 1,
                        if(@f := t.firm, 1, 1)
                       )
             ) as rn
      from mytable t cross join
           (select @f := '', @rn := 0) params
      order by t.firm, t.year desc
     ) t
where rn = 2;

您的版本有一个致命缺陷:它与group by一起使用select *。选择中有未聚合的列,这些列不是group by键。这是损坏的SQL,几乎在所有数据库中都将失败,并且会使用最新版本的MySQL中的默认设置。

如果意图是“ n”是最近一年之前的年数(很好,由1抵消),则联接可以起作用:

select t.*
from mytable t join
     (select firm, max(year) as max_year
      from mytable
      group by firm
     ) f
     on t.firm = f.firm and t.year = f.max_year - (2 - 1);

答案 1 :(得分:0)

将LAG与MySQL 8中引入的窗口函数一起使用会更容易