Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 将多个记录折叠为具有多列的单个记录_Sql_Db2 - Fatal编程技术网

Sql 将多个记录折叠为具有多列的单个记录

Sql 将多个记录折叠为具有多列的单个记录,sql,db2,Sql,Db2,在我维护的一个程序中,客户给了我们一个500行左右的SQL语句。它用于生成具有固定长度记录的平面文件,以便将数据传输到另一家大企业。因为它是一个巨大的平面文件,所以它不是关系型的,标准的标准数据格式也被压缩了。因此,如果您有一个记录可以关联多个代码,在本例中最多19个,那么它们都已写入平面文件中的单行但单独的字段中 注:此示例已简化 数据可能如下所示,有三个表: RECORDS record_id firstname lastname ----------------------

在我维护的一个程序中,客户给了我们一个500行左右的SQL语句。它用于生成具有固定长度记录的平面文件,以便将数据传输到另一家大企业。因为它是一个巨大的平面文件,所以它不是关系型的,标准的标准数据格式也被压缩了。因此,如果您有一个记录可以关联多个代码,在本例中最多19个,那么它们都已写入平面文件中的单行但单独的字段中

注:此示例已简化

数据可能如下所示,有三个表:

RECORDS
record_id   firstname   lastname    
--------------------------------    
123         Bob         Schmidt
324         George      Washington
325         Ronald      Reagan
290         George      Clooney


CODE_TABLE
code_id     code_cd     code_txt
--------------------------------
5           3           President
2           4           Actor    
3           7           Plumber


CODES_FOR_RECORDS
record_id   code_cd
-------------------
123         7    
325         3
290         4
324         3
325         4
123         4
这需要生成如下记录:

firstname   lastname    code1       code2       code3
Bob         Schmidt     Actor       Plumber     NULL
George      Washington  President   NULL        NULL
Ronald      Reagon      Actor       President   NULL
George      Clooney     Actor       NULL        NULL
我们得到的当前查询部分如下所示,但有19个代码列,而不是5个:

select 
    x.record_id,
    max(case when  x.rankk = 1  then code_txt end) as CodeColumn1,
    max(case when  x.rankk = 2  then code_txt end) as CodeColumn2,
    max(case when  x.rankk = 3  then code_txt end) as CodeColumn3,
    max(case when  x.rankk = 4  then code_txt end) as CodeColumn4,
    max(case when  x.rankk = 5  then code_txt end) as CodeColumn5,
from 
    (
        select 
            r.record_id,
            ct.code_txt as ctag ,
            dense_rank() over (partition by r.record_id order by cfr.code_id) as rankk
        from            
            records as r
            codes_for_records as cfr,
            code_table as ct
        where
            r.record_id = cfr.record_id
            and ct.code_cd = cfr.code_cd
            and cfr.code_cd is not null
            and ct.code_txt not like '%V%'
    ) as x
where
    x.record_id is not null
group by
    x.record_id  
为了简单起见,我删减了一些内容,但实际的语句包括一个内部查询和一个连接以及更多的where条件,但这应该能让人明白这一点。我的大脑告诉我必须有更好的方法,但我不是SQL专家。如果有帮助的话,我们正在使用DB2V8。代码必须在单独的列中,因此不能将内容合并到单个字符串中。有比这更干净的解决方案吗

更新:


我最终只是重新编写了原始查询,它使用了丑陋的MAX business,但由于重新编写了其他部分,因此总体上查询的可读性要高得多

可能的解决方案之一是使用递归查询:

with recursive_view (record_id, rankk, final) as
(
  select
    record_id, 
    rankk,
    cast (ctag as varchar (100))
  from inner_query t1

  union all 

  select
    t1.record_id,
    t1.rankk,
    /* all formatting here */
    cast (t2.final || ',' || t1.ctag as varchar (100))
  from 
    inner_query t1,
    recursive_view t2
  where 
    t2.rankk < t1.rankk
    and t1.record_id = t2.record_id
    and locate(t1.ctag, t2.final) = 0
)
select record_id, final from recursive_view;

我不能保证它能工作,但希望它能有所帮助。另一种方法是使用自定义聚合函数。

听起来您正在寻找的是

请注意,我以前从未亲自做过这件事。我把这本书当作参考书

您可能需要包含记录id以说明重复的名称


编辑:添加分组依据。

当我编写代码手动转换数据时,该过程很少少于1000行。这段代码对我来说非常简单和直接,也许是因为我对SQL不太熟悉,因为对我来说这似乎有点复杂。它的一部分是1000行,当分成逻辑块时,这并不坏。500行SQL是如此相互关联,好像意大利面是另一回事,IMHO。谢谢你的建议。但是,每个代码都需要保留为其on collumn。它不能连接成一个巨大的字符串。它可以通过填充来格式化,看起来像一堆列。否则,如果没有pivot和DynamicSQL,您将被迫使用重复的maxcase构造。我试试看。我还是觉得麦克斯的生意很难看。
WITH joined_table(firstname, lastname, code_txt, rankk) AS
(
SELECT
  r.firstname,
  r.lastname,
  ct.code_txt,
  dense_rank() over (partition by r.record_id order by cfr.code_id) as rankk
FROM
  records r
INNER JOIN
  codes_for_records cfr
  ON r.record_id = cfr.record_id
INNER JOIN
  codes_table ct
  ON ct.code_cd = cfr.code_cd
),

decoded_table(firstname, lastname,
  CodeColumn1, CodeColumn2, CodeColumn3, CodeColumn4, CodeColumn5) AS
(
  SELECT
    firstname,
    lastname,
    DECODE(rankk, 1, code_txt),
    DECODE(rankk, 2, code_txt),
    DECODE(rankk, 3, code_txt),
    DECODE(rankk, 4, code_txt),
    DECODE(rankk, 5, code_txt)
  FROM
    joined_table jt
)

SELECT
  firstname,
  lastname,
  MAX(CodeColumn1),
  MAX(CodeColumn2),
  MAX(CodeColumn3),
  MAX(CodeColumn4),
  MAX(CodeColumn5)
FROM
  decoded_table dt
GROUP BY
  firstname,
  lastname;