【问题标题】:How to concat cells from same table but different row?如何连接来自同一张表但不同行的单元格?
【发布时间】:2019-02-19 14:56:30
【问题描述】:

我有以下问题。 我的表中有一些几乎相同的行,我需要一些单元格与上面的单元格连接。 我当前的 Select 语句如下所示:

Select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp
      ,regexp_replace(regexp_replace(LISTAGG(bltxt,' '),'\s+',' '),'¯+','') AS Text 
from atdata.bip105
where bltspriso = 'DEAT'
group by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp

输出看起来像这样

BLTGS1-6 类似于类别,例如第一个条目看起来像 (0 = empty/null):“1-0-0-0-0-0-0-0 AKTIVA”第二个条目看起来像“1 -1-0-0-0-0-0 BTIVA”。 SO BTIVA 是 AKTIVA 的一个子类别。 BLTUGP 中有一些行包含 1 或 2。如果是这种情况,我想将TEXT 条目连接到上面的第一行,它不包含BLTUGP 中的数字。所以关于文本,它应该看起来像,例如:

BLTUGP| TEXT
      | TOM
 1    | likes salat.
 2    | likes tomatoes.

此示例的输出应如下所示:

BLTUGP| TEXT
      | TOM
 1    | TOM likes salat.
 2    | TOM like tomatoes.

例如,如您所见,带有“erhaltene Anzahlungen auf Bestellung”的行应如下所示:

2 - 1 - 12 - 01 - 007 - 01 - "erhaltene Anzahlungen auf Bestellung davon mit einer Restlaufzeit von bis zu einem Jahr" 

2 - 1 - 12 - 01 - 007 - 02 - "erhaltene Anzahlungen auf Bestellung davon mit einer Restlaufzeit von mehr als einem Jahr"

....但我还需要所有 bltugp 为空/空的行。 附加信息!我无法操作/更改源表。

提前致谢!

更新: 我试过了

with 

tbl_wougp as

  (Select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp ,regexp_replace(regexp_replace(LISTAGG(bltxt,' '),'\s+',' '),'¯+','') AS Text

    from atdata.bip105

    where bltspriso = 'DEAT' and bltugp=''

    group by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp),

tbl_wugp as

  (Select u.bltgs1, u.bltgs2, u.bltgs3, u.bltgs4, u.bltgs5, u.bltgs6, u.bltugp, concat(concat(trim(h.bltxt), ' '), trim(u.bltxt))  as Text from 

    (select * from atdata.bip105 where bltspriso = 'DEAT' and bltugp='') h right join

    (select * from atdata.bip105 where bltspriso = 'DEAT' and bltugp<>'') u

   on u.bltgs1=h.bltgs1 and u.bltgs2=h.bltgs2 and u.bltgs3=h.bltgs3 and u.bltgs4=h.bltgs4 and u.bltgs5=h.bltgs5 and u.bltgs6=u.bltgs6 

)

select * from tbl_wougp

union 

select * from tbl_wugp

order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6;

这几乎可以按预期工作,但有些行似乎加倍,我不知道为什么。

【问题讨论】:

  • 请不要发布图片。不是每个人都可以访问图像转储站点。此外,如果您要发布示例输入数据,这将很有帮助。如果不了解您的出发点,就很难想象如何获得理想的结果。
  • 您获得多行,因为您将所有其他列包含在分组依据中;例如,您可能需要聚合 bltgup。但是将您拉出的两行作为文本,对于 2/1/12/01/007,您有一行 bltgup null,那么您的逻辑是什么 - 将该空值文本添加到所有其他非空值 -值行的文本?
  • @AlexPoole 这是一份资产负债表报告,有些账户的含义几乎相同。它们之间的区别在于一个剩余时间不到 1 年,另一个剩余时间超过 1 年,但我还需要 bltgup 为空的行
  • 请编辑您的问题以充分解释逻辑。对于bltgs5 = '007',您有三行,一为空,二为非空;您的示例输出表明您只想查看非空行,但前面带有空值。再次查看图像(!),您对bltgs5 = '021' 有不同的场景,其中设置了bltgs6 的几行似乎遵循该模式,但还有bltgs6bltugp 均为空的单行。那么你也想在输出中看到那一行吗?还是会发生其他事情?
  • @AlexPoole 对不起这张照片。我会试着解释一下。数字(bltgs)就像类别一样工作。例如(0 表示空):“1-0-0-0-0-0 Aktiva”是最高类别,“1-1-01-0-0-0 Anlagenvermögen”是 Aktiva 的子类别,因此on.. 所以你可以在图片中看到“2-1-12-01-21-0-0 sonstige Verbindlichkeiten”包含所有行作为子类别,直到 bltgs5(第 21 号)机会,例如 22。

标签: sql oracle select string-aggregation lead


【解决方案1】:

您可以使用LISTAGG(从 Oracle 11.2 开始)来执行此操作。这是link 说明如何执行此操作。

如果您在较低版本的 Oracle 上运行,则可以使用 WM_CONCAT(如果支持)。

【讨论】:

  • OP发布的代码已经使用listagg()。你需要解释他们可以更好地使用它。
【解决方案2】:

自行加入您当前的结果,如下例所示:

-- sample data
with your_query(bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltugp, text) as (
  select 2, 1, 12, '01', '007', null, 'Tom wants to'  from dual union all
  select 2, 1, 12, '01', '007', '01', 'sleep'         from dual union all
  select 2, 1, 12, '01', '007', '02', 'play'          from dual union all
  select 2, 1, 12, '01', '008', null, 'Mark is'       from dual union all
  select 2, 1, 12, '01', '008', '01', 'cheerful'      from dual union all
  select 2, 1, 12, '01', '008', '02', 'sad'           from dual )
-- end of sample data

select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, b.bltugp,
       a.text||' '||b.text text
  from your_query a 
  join your_query b using (bltgs1, bltgs2, bltgs3, bltgs4, bltgs5)
  where (a.bltugp is null and b.bltugp = '01') 
     or (a.bltugp is null and b.bltugp = '02')
  order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, b.bltugp

...我们得到:

BLTGS1     BLTGS2     BLTGS3 BLTGS4 BLTGS5 BLTUGP TEXT
------ ---------- ---------- ------ ------ ------ -------------------------
     2          1         12 01     007    01     Tom wants to sleep
     2          1         12 01     007    02     Tom wants to play
     2          1         12 01     008    01     Mark is cheerful
     2          1         12 01     008    02     Mark is sad

【讨论】:

    【解决方案3】:

    对于其他列值的每个组合,您似乎希望将与空 bltugp 关联的文本添加到与所有非空值关联的文本之前。

    一种方法是使用连接和分析函数来查找要添加的基于 null 的文本:

    max(case when bltugp is null then bltxt end)
            over (partition by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz)
          || bltxt
    

    这会给你三行:

        BLTGS1     BLTGS2     BLTGS3 BL BLT BLTGS6 BL TEXT                                                                                                    
    ---------- ---------- ---------- -- --- ------ -- --------------------------------------------------------------------------------------------------------
             2          1         12 01 007        01 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von bis zu einem Jahr                  
             2          1         12 01 007        02 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von mehr als einem Jahr                
             2          1         12 01 007           erhaltene Anzahlungen auf Bestellungerhaltene Anzahlungen auf Bestellung                                
    

    ...然后丢弃你不想要的那个。作为示例,将这些行和其他一些可能有趣的行作为示例数据:

    -- CTE for dummy data
    with bip105 (bltspriso, blttkz, bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, bltxt) as (
      select 'DEAT', 42, 2, 1, 12, '01', '006', null, '02', 'davon mit einer Restlaufzeit von mehr als einem Jahr' from dual
      union all
      select 'DEAT', 42, 2, 1, 12, '01', '007', null, null, 'erhaltene Anzahlungen auf Bestellung' from dual
      union all
      select 'DEAT', 42, 2, 1, 12, '01', '007', null, '01', 'davon mit einer Restlaufzeit von bis zu einem Jahr' from dual
      union all
      select 'DEAT', 42, 2, 1, 12, '01', '007', null, '02', 'davon mit einer Restlaufzeit von mehr als einem Jahr' from dual
      union all
      select 'DEAT', 42, 2, 1, 12, '01', '021', null, null, 'sonstige Verbindlichkeiten' from dual
    )
    -- actual query
    select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, text
    from (
      select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
        , max(case when bltugp is null then bltxt end)
            over (partition by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz)
          || bltxt as text
      from bip105
      where bltspriso = 'DEAT'
    )
    where bltugp is not null
    order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp;
    
        BLTGS1     BLTGS2     BLTGS3 BL BLT BLTGS6 BL TEXT                                                                                                    
    ---------- ---------- ---------- -- --- ------ -- --------------------------------------------------------------------------------------------------------
             2          1         12 01 006        02 davon mit einer Restlaufzeit von mehr als einem Jahr                                                    
             2          1         12 01 007        01 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von bis zu einem Jahr                  
             2          1         12 01 007        02 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von mehr als einem Jahr                
    

    如果您还想显示所有基于 null 的行,您可以删除过滤器,但还需要停止将该值附加到自身;可能更简单的方法,但这是使用另一种 case 表达式的方法:

    select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, text
    from (
      select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
        , max(case when bltugp is null then bltxt end)
            over (partition by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz)
          || case when bltugp is not null then bltxt end as text
      from bip105
      where bltspriso = 'DEAT'
    )
    order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
    
        BLTGS1     BLTGS2     BLTGS3 BL BLT BLTGS6 BL TEXT                                                                                                    
    ---------- ---------- ---------- -- --- ------ -- --------------------------------------------------------------------------------------------------------
             2          1         12 01 006        02 davon mit einer Restlaufzeit von mehr als einem Jahr                                                    
             2          1         12 01 007        01 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von bis zu einem Jahr                  
             2          1         12 01 007        02 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von mehr als einem Jahr                
             2          1         12 01 007           erhaltene Anzahlungen auf Bestellung                                                                    
             2          1         12 01 021           sonstige Verbindlichkeiten                                                                              
    

    或者,如果您只想在该组合没有其他行时查看基于 null 的行,您可以计算每个组合的非空条目,并且仅在存在任何非空时排除空值(暗示null 一个已预先添加,并且不需要单独使用 - 如果这确实是您需要的规则):

    select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, text
    from (
      select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
        , max(case when bltugp is null then bltxt end)
            over (partition by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz)
          || case when bltugp is not null then bltxt end as text
        , count(bltugp) over (partition by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz)
          as non_null_count
      from bip105
      where bltspriso = 'DEAT'
    )
    where non_null_count = 0 or bltugp is not null
    order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp;
    
        BLTGS1     BLTGS2     BLTGS3 BL BLT BLTGS6 BL TEXT                                                                                                    
    ---------- ---------- ---------- -- --- ------ -- --------------------------------------------------------------------------------------------------------
             2          1         12 01 006        02 davon mit einer Restlaufzeit von mehr als einem Jahr                                                    
             2          1         12 01 007        01 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von bis zu einem Jahr                  
             2          1         12 01 007        02 erhaltene Anzahlungen auf Bestellungdavon mit einer Restlaufzeit von mehr als einem Jahr                
             2          1         12 01 021           sonstige Verbindlichkeiten                                                                              
    

    目前还不清楚你想看到什么......

    【讨论】:

      【解决方案4】:

      我设法找到了解决办法

      with 
      
      tbl_wougp as
      (Select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp ,regexp_replace(regexp_replace(LISTAGG(bltxt,' '),'\s+',' '),'¯+','') AS Text
      from atdata.bip105
      where bltspriso = 'DEAT' and bltugp=''
      group by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp),
      
      tbl_wugp as
      (Select bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp ,regexp_replace(regexp_replace(LISTAGG(bltxt,' '),'\s+',' '),'¯+','') AS Text
      from atdata.bip105
      where bltspriso = 'DEAT' and bltugp<>''
      group by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp)
      
      select * from tbl_wougp
      union
      select u.bltgs1, u.bltgs2, u.bltgs3, u.bltgs4, u.bltgs5, u.bltgs6, u.bltugp, concat(concat(trim(h.text), ' '), trim(u.text)) as Text
      from tbl_wugp u left join tbl_wougp h
      on u.bltgs1=h.bltgs1 and u.bltgs2=h.bltgs2 and u.bltgs3=h.bltgs3 and u.bltgs4=h.bltgs4 and u.bltgs5=h.bltgs5 and u.bltgs6=h.bltgs6 
      order by bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, text;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多