当该行的 clos 与上一行具有重复值时,如何进行 sql Select 查询,以便在后续行中将某些列留空?

Posted

技术标签:

【中文标题】当该行的 clos 与上一行具有重复值时,如何进行 sql Select 查询,以便在后续行中将某些列留空?【英文标题】:How to have sql Select query such that some columns are left blank in subsequent rows when clos of that row have a duplicate value from the above row? 【发布时间】:2020-06-19 07:14:43 【问题描述】:

我有一张这样的桌子。

 Name|  Id |  cost
  ----------------
  A  |  1  |  1000
  ----------------
  A  |  1  |  2000
  ----------------
  B  |  2  |  3000
  ----------------
  B  |  2  |  4000

注意:数据已经排好序了

我需要的结果是:

 Name|  Id |  cost
  ----------------
  A  |  1  |  1000
  ----------------
     |     |  2000
  ----------------
  B  |  2  |  3000
  ----------------
     |     |  4000

由于我们的查询中已经存在“A”,因此下一行在“Name”中应该有一个空白值,并且与“A”关联的 id 也是 1,它也是重复的,因此它也应该是空白的。 B的情况类似。

如何在单个选择查询中实现这一点?

【问题讨论】:

要在某处显示结果吗? 行号上的子句超过名称上的窗口时的情况 already in sorted order ... 是cost 列的排序顺序吗?因为,如果不是,那么您所感知的顺序甚至都不存在。 这是在表示层而不是 T-SQL 中完成的最佳工作。 【参考方案1】:

你可以使用row_number():

select
    case when row_number() over(partition by name, id order by cost) = 1
        then name
    end name,
    case when row_number() over(partition by name, id order by cost) = 1
        then id
    end id,
    cost
from mytable

这假设您想要由cost 排序的(name, id) 元组(如您的示例数据所示)。如果要使用另一个排序列,则可以更改窗口函数的order by 子句。

【讨论】:

你怎么知道cost 在这里提供了 OP 想要的排序? @TimBiegeleisen:我正在对此发表评论。这似乎正是 OP 想要的(它与他们的样本数据匹配)——当然,可以使用另一列。【参考方案2】:

我们可以吗

with tb(Name,  Id ,  cost) as (
 select 'A'  ,  1  ,  1000 union all
  select 'A'  ,  1  ,  2000 union all
  select 'B'  ,  2  ,  3000 union all
  select 'B'  ,  2  ,  4000
  )

  select
    case when Row_Nb = 1 then Name else '' end as Name
    ,  case when Row_Nb = 1 then Id else null end as Id 
    ,  cost
  from(
    select row_number() OVER(partition by  Name, id order by cost) AS Row_Nb, tb.*
    from tb
  )x

【讨论】:

【参考方案3】:

我不建议将此作为数据库查询。结果集将包含没有意义的行,除非您看到它们上方的行——这不是 SQL 方式。

我建议首先汇总并将成本放在一行中:

select name, id, string_agg(cost, ', ') as costs
from t
group by name, id;

如果您确实坚持使用此结果集,那么在外部查询中具有order by 非常重要,因为没有order by,结果可以按任何顺序排列。因此,我认为最好的解决方案是:

select (case when seqnum = 1 then name end) as name,
       (case when seqnum = 1 then id end) as id,
       cost
from (select t.*, row_number() over (partition by name, id order by cost) as seqnum
      from t
     ) t
order by name, id, seqnum

【讨论】:

以上是关于当该行的 clos 与上一行具有重复值时,如何进行 sql Select 查询,以便在后续行中将某些列留空?的主要内容,如果未能解决你的问题,请参考以下文章

当DataFrame具有不同的值时,如何将重复行合并为一个

如何选择具有字段重复值的每一行

当另一个框在excel(VBA)中具有特定值时,如何引用msgBox中的单元格。

如何选择(所有)表 1 中的一行,该行具有与表 2 相同的另一行

[引用数组的多个值时,使用Python列表理解排除重复项

根据条件 pandas 删除 DataFrame 中的重复行