【问题标题】:How to select info from row above?如何从上面的行中选择信息?
【发布时间】:2012-01-20 15:07:46
【问题描述】:

我想在我的表中添加一列,如下所示: 这只是表格结构的一个示例,实际表格超过 10.000 行。

No_   Name       Account_Type    Subgroup     (New_Column)
100   Sales      3               
200   Underwear  0               250          *100
300   Bikes      0               250          *100
400   Profit     3                             
500   Cash       0               450          *400

因此,每当“子组”中有一个值时,我希望 (New_Column) 从上面的行中获取值 [No_]

No_   Name       Account_Type    Subgroup     (New_Column)
100   Sales      3               
150   TotalSales 3
200   Underwear  0               250          *150
300   Bikes      0               250          *150
400   Profit     3                             
500   Cash       0               450          *400

在某些情况下,表格就像上面一样,上面有两个“标题”。在这种情况下,我还想要上面的第一行(150)。

这是光标的情况还是您有什么建议?

数据按No_排序

--编辑--

从第一行开始,然后贯穿整个表格: 有没有办法可以将 [No_] 的值存储在 [Subgroup] 为 '' 的位置? 然后在下面每一行的 (New_Column) 中插入此 [No_] 值,在 [Subgroup] 行中具有值。 而当 [Subgroup] 行为空时,该过程将继续进行,在 (New_Column) 中插入下一个 [No_] 值,即如果下一行在 [Subgroup] 中有值

这是我正在尝试做的更好的图像:

【问题讨论】:

  • 我建议适当的标准化:en.wikipedia.org/wiki/Database_normalization
  • 你如何定义上面的行?? SQL Server 没有任何“内置”排序 - 除非 明确指定 ORDER BY 子句,否则没有排序 - 所以也没有 row above。 ...
  • 请进一步扩展“上面有两个“标题”的位置”。请澄清“标题”和“上方”是什么。我只是不明白你的意思。谢谢!
  • 在我的例子中,上面的行是 [Subgroup) 中的值上面的行。我正在考虑以某种方式使用过滤器 [where subgroup = '' ]?
  • @AceAlfred - 人们试图让您知道诸如“以上”之类的术语在 SQL 中是没有意义的,除非定义了特定的顺序(例如,出于此查询的目的,它们是否按 No_ 排序?)

标签: sql sql-server tsql sql-server-2008-r2 database-cursor


【解决方案1】:

SQL Server 2012 建议使用窗口偏移函数。 在这种情况下:滞后

类似这样的:

SELECT [No_]
  ,[Name]
  ,[Account_Type]
  ,[Subgroup]
  ,LAG([No_]) OVER(PARTITION BY [Subgroup]
ORDER BY [No_]) as [PrevValue]
FROM table

这是来自 MS 的示例: http://technet.microsoft.com/en-us/library/hh231256.aspx

【讨论】:

    【解决方案2】:

    ROW_NUMBER 函数可让您找出行的编号,但由于它是一个窗口函数,您必须使用公用表表达式 (CTE) 将表与其自身连接起来。

    WITH cte AS
    (
        SELECT [No_], Name, Account_Type, Subgroup, [Row] = ROW_NUMBER() OVER (ORDER BY [No_])
        FROM table
    )
    SELECT t1.*, t2.[No_]
    FROM cte t1 
    LEFT JOIN cte t2 ON t1.Row = t2.Row - 1
    

    希望这会有所帮助。

    【讨论】:

    • 那些ROW_NUMBER() 值将被有效地随机分配给表。如果 CTE 中的值被评估两次(因为它们可能与此自联接一样),则不能保证在第二遍分配的 row_numbers 与第一遍的值有任何关联。事实上,您最终可以将每一行都连接起来。
    • @Damien_The_Unbeliever:如果窗口函数被定义为over (order by [No_]),它可能会起作用——SQL Server 也该实现lag() 函数了
    • @a_horse_with_no_name - 哦,同意。按基础表中唯一的列排序是很好且可预测的。放弃而不定义订单是查询使用示例数据然后在生产中失败(现在,或者 6 个月后,或者只是间歇性地)的好方法
    • ORDER BY 1 表示它将按表中的第一列排序,而不是整数 (1)。所有这一切都基于第一列 [No_] 是主键的假设,并产生“上方行”标准所需的正确顺序。我将进行编辑以使我的窗口函数不那么模棱两可。感谢您的澄清。
    • 如果 SQL Server 最终像大多数其他 DBMS 一样支持lag() 窗口功能,这将非常容易......
    【解决方案3】:

    下一个查询将返回 parent 行的名称而不是行本身,即 Sales、Underwear、Bikes 的 Sales;和利润换利润,现金:

    select ISNULL(t2.Name, t1.Name)
    from table t1
    left join table t2 on t1.NewColumn = t2.No
    

    【讨论】:

      【解决方案4】:

      所以在 SQL Server 2008 中,我创建了包含 3 个值的测试表:

      create table #ttable
      (
          id int primary key identity,
          number int,
          number_prev int
      )
      Go
      Insert Into #ttable (number) 
      Output inserted.id
      Values (10), (20), (30);
      

      插入表格,你需要的(至少如果理解正确的话)看起来像这样:

      declare @new_value int;
      set @new_value = 13; -- NEW value
      Insert Into #ttable (number, number_prev)
      Values (@new_value, 
          (Select Max(number) From #ttable t Where t.number < @new_value)) 
      

      [此部分已添加] 并与子组一起使用 - 只需修改内部选择以过滤掉它:

      Select Max(number) From #ttable t 
      Where t.number < @new_value And Subgroup != @Subgroup
      

      【讨论】:

      • 其实可以避免使用临时表,如果创建table类型的变量:declare @ttable table ( all the same )
      • 为什么要避免使用临时表?在这个例子中它并不重要。
      • 因为表变量对服务器的压力远低于临时表。因此,为了增加答案的有用负载,最好在特定情况下提出最佳解决方案。这将使 SO 越来越好。
      【解决方案5】:
      SELECT
            No_
          , Name 
          , Account_Type 
          , Subgroup 
          , ( SELECT MAX(above.No_) 
              FROM TableX AS above
              WHERE above.No_ < a.No_
                AND above.Account_Type = 3
                AND a.Account_Type <> 3
            ) AS NewColumn
      FROM
            TableX AS a
      

      【讨论】:

        猜你喜欢
        • 2020-06-16
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 2023-03-21
        • 1970-01-01
        • 2019-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多