[英]How to retrieve “last” non-zero values from multiple columns?
Considering an ordered table with 11 columns: 考虑一个有11列的有序表:
timespan, val1, val2, val3, val4, val5, val6, val7, val8, val9 and val10
Suppose a set of records like: 假设一组记录如:
timespan val1 val2 val3 val4 val5 val6 val7 val8 val9 val10
10/09/2011 0 0 60 80 40 0 0 40 80 0
10/10/2011 0 10 90 30 70 50 50 70 30 90
10/11/2011 10 0 20 0 0 60 60 0 0 20
I need a SQL query (for SQL Server 2012) which returns the last (in time) non zero values for all columns, val1, val2, ..., that is, 我需要一个SQL查询(对于SQL Server 2012),它返回所有列的最后(及时)非零值,val1,val2,...,即
val1 val2 val3 val4 val5 val6 val7 val8 val9 val10
10 10 20 30 70 60 60 70 30 20
A similar question can be found at Subquery: how to retrieve the last non-zero value from a column? 在Subquery中可以找到类似的问题:如何从列中检索最后一个非零值? but it only works for one column and the generalisation to include more columns (as in this case) seems not practical.
但它只适用于一列,并且包含更多列的泛化(如本例所示)似乎不实用。
You can use first_value()
: 你可以使用
first_value()
:
select distinct first_value(val1) over (order by sign(val1) desc, timespan desc) as val1,
first_value(val2) over (order by sign(val2) desc, timespan desc) as val2,
. . .
from t;
Generally, I am opposed to using select distinct
as a replacement for an aggregation query. 通常,我反对使用
select distinct
作为聚合查询的替代。 Unfortunately, SQL Server supports first_value()
as a window function but does not provide an equivalent for aggregation. 不幸的是,SQL Server支持
first_value()
作为窗口函数,但不提供聚合的等效项。
Note: the sign()
function is used to put the zero values last. 注意:
sign()
函数用于将零值放在最后。 If you can have negative values, then use abs(sign())
. 如果你可以有负值,那么使用
abs(sign())
。
Another option is a quick unpivot followed by a pivot 另一种选择是快速拆卸,然后是枢轴
Example 例
Select *
From (
Select top 1 with ties item,value
From YourTable
UnPivot ( Value for Item in (val1,val2,val3,val4,val5,val6,val7,val8,val9,val10) ) u
Where value<>0
Order by Row_Number() over (Partition By item Order by timespan desc)
) src
Pivot (max(value) For item in (val1,val2,val3,val4,val5,val6,val7,val8,val9,val10) ) p
Returns 返回
val1 val2 val3 val4 val5 val6 val7 val8 val9 val10
10 10 20 30 70 60 60 70 30 20
You can use something like below. 你可以使用下面的东西。 1. logic is to first unpivot values and then remove 0 entries and then calculate last non zero value as row_num=1.
1.逻辑是首先取消值,然后删除0个条目,然后计算最后的非零值为row_num = 1。
Query is below 查询如下
create table t
(timespan date,val1 int,val2 int,val3 int,val4 int,val5 int,val6 int,val7 int,val8 int,val9 int,val10 int);
insert into t values
('10/09/2011', 0, 0,60,80,40, 0, 0,40,80, 0)
,('10/10/2011', 0,10,90,30,70,50,50,70,30,90)
,('10/11/2011',10, 0,20, 0, 0,60,60, 0, 0,20);
select *
from
(
select
value, Columns
from
(
select
timespan,
value,
Columns,
row_number() over(partition by Columns order by timespan desc) r
from
(select * from t)s
unpivot
(
value for Columns in
([val1],[val2],[val3],[val4],[val5],[val6],[val7],[val8],[val9],[val10])
)up
where value<>0
) t
where r=1
)s
pivot
(
max(value) for Columns in
([val1],[val2],[val3],[val4],[val5],[val6],[val7],[val8],[val9],[val10])
)p
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.