【问题标题】:How to retrieve "last" non-zero values from multiple columns?如何从多列中检索“最后一个”非零值?
【发布时间】:2017-10-11 13:42:55
【问题描述】:

考虑一个有 11 列的有序表:
timespan, val1, val2, val3, val4, val5, val6, val7, val8, val9 and val10

假设一组记录如下:

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

我需要一个 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

可以在Subquery: how to retrieve the last non-zero value from a column? 找到类似的问题,但它仅适用于一列,并且包含更多列的概括(如本例)似乎不切实际。

【问题讨论】:

    标签: sql sql-server tsql sql-server-2012


    【解决方案1】:

    你可以使用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;
    

    一般来说,我反对使用select distinct 作为聚合查询的替代品。不幸的是,SQL Server 支持 first_value() 作为窗口函数,但不提供聚合的等效项。

    注意:sign() 函数用于将零值放在最后。如果可以有负值,请使用abs(sign())。

    【讨论】:

      【解决方案2】:

      另一种选择是快速反轴,然后是轴

      示例

      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
      

      退货

      val1    val2    val3    val4    val5    val6    val7    val8    val9    val10
      10      10      20      30      70      60      60      70      30      20
      

      【讨论】:

      • @scsimon 谢谢,它支持 2012 年之前的纯愚蠢运气。老实说,我什至从未考虑过这一点。 :)
      【解决方案3】:

      您可以使用如下所示的内容。 1.逻辑是先unpivot值,然后删除0个条目,然后将最后一个非零值计算为row_num = 1。

      1. 然后再次旋转以获得结果。

      查询如下

      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
      

      See working demo

      【讨论】:

        猜你喜欢
        • 2011-09-16
        • 2022-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-13
        • 2021-05-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多