Sql 在非结构化表中合并行

Sql 在非结构化表中合并行,sql,oracle,postgresql,oracle11g,Sql,Oracle,Postgresql,Oracle11g,我有一个非结构化表,其中(1)itemID有多个与其关联的receptCodes。我需要做的是在一行中显示与不同orderID关联的每个receptCode。当前表结构与此类似: itemID | receptString ============================= itemID1 | receptString1 itemID1 | receptString2 itemID1 | receptString3 itemID1 | recep

我有一个非结构化表,其中(1)itemID有多个与其关联的receptCodes。我需要做的是在一行中显示与不同orderID关联的每个receptCode。当前表结构与此类似:

    itemID  | receptString
=============================
    itemID1 | receptString1
    itemID1 | receptString2
    itemID1 | receptString3
    itemID1 | receptString4
    itemID2 | receptString5
    itemID2 | receptString6
期望输出:

    itemID    | receptString | receptString  | receptString | receptString |
    ============================================================================
    itemID1  | receptString1 | receptString2 | receptString3 | receptString4 |
    itemID2  | receptString5 | receptString6 |
编写此查询的正确方法是什么?我尝试使用多个CASE语句和groupby,但在这一点上我很难理解逻辑。每个orderID最多只能有(5)个ReceptString,但可以在1到5个ReceptString之间变化。ReceptString可以是字符、符号和数字的组合。如果出现空值,我不担心。这只是我需要的一部分,但也是我正在努力解决的问题。我正在PostgreSQL和Oracle SQL中测试这一点

*更新*


谢谢大家的建议。问题最终比我们最初预期的要严重一些(我提供的示例表是一个非常大的饼中的一小块),因此我们决定采取不同的方法。再次感谢

oracle11gr2及更高版本上,您可以使用listag进行字符串聚合

SELECT itemID  ,
  LISTAGG(receptString, ' | ') WITHIN GROUP (
ORDER BY receptString) AS receptString
FROM table_name
GROUP BY itemID
ORDER BY itemID;
查看不同数据库版本上的其他方法


请记住,这是字符串聚合,而不是轴。您将把这些行聚合为一个带分隔符的字符串行。

PostgreSQL

以下面为例

create table ft (itemid text,receptstring text);
insert into ft values
('itemID1','receptString1'),
('itemID1','receptString2'),
('itemID1','receptString3'),
('itemID1','receptString4'),
('itemID2','receptString5'),
('itemID2','receptString6');
通过使用

输出:

itemid  receptstring  receptstring    receptstring   receptstring    receptstring
------- ------------- --------------- --------------- --------------- --------------- 
itemID1 receptString1 receptString2   receptString3   receptString4   NULL
itemID2 receptString5 receptString6   NULL            NULL            NULL

另一种方式

,如果某个特定的
itemID
具有超过1600或250个
receptString
?。所以我建议你做如下的事情

在PostgreSQL中使用

 select "itemID"
       ,string_agg("receptString",',' ORDER BY "receptString") receptString 
 from tbl
 group by "itemID"
第二列存储11g中测试的特定
itemID

的所有
receptString

这里我使用一个临时分隔符作为
~
。如果您认为您的字符串字符具有此属性,则可以使用
|
chr(10)
chr(13)
或任何其他分隔符。它会很好用的

此外,列名不能与所需的相同。我附加了1,2,3等等。你可以随意改变它们

    with tbl1 (itemID  , receptString) as(
    select 'itemID1','receptString1' from dual union all
    select 'itemID1','receptString2' from dual union all
    select 'itemID1','receptString3' from dual union all
    select 'itemID1','receptString4' from dual union all
    select 'itemID2','receptString5' from dual union all
    select 'itemID2','receptString6' from dual
    ), tbl2 as(
    select itemid,listagg(receptString,'~') within group (order by itemid) || '~' as concstr
    from tbl1
    group by itemid
    )
     SELECT  tbl2.itemid,REGEXP_SUBSTR(concstr ,'([^~]*)(\~)', 1, 1, NULL, 1 ) as receptString1,
      REGEXP_SUBSTR(concstr ,'([^~]*)(\~)', 1, 2, NULL, 1 ) as receptString2,
      REGEXP_SUBSTR(concstr ,'([^~]*)(\~)', 1, 3, NULL, 1 ) as receptString3,
      REGEXP_SUBSTR(concstr ,'([^~]*)(\~)', 1, 4, NULL, 1 ) as receptString4,
      REGEXP_SUBSTR(concstr ,'([^~]*)(\~)', 1, 5, NULL, 1 ) as receptString5
      from tbl2
首先,我使用listag连接列并添加分隔符。然后我使用regep_substr将它们分隔成列。对于不存在的列,根据此输出,它们将为null

输出

 ITEMID     RECEPTSTRING1   RECEPTSTRING2   RECEPTSTRING3   RECEPTSTRING4  RECEPTSTRING5
 itemID1    receptString1   receptString2   receptString3   receptString4   
 itemID2    receptString5   receptString6           

最多有多少行可以有一个
receptString
?如果你说
orderID
,你的意思是
itemID
,因为我在你的示例数据中没有看到
orderID
?@Abootman-看看我的方法是否适用于你,如果适用,请接受。问题可以解决。否则请指定问题,以便我们可以更正。注意:原始表是结构化的。结果表违反了1NF(receptStringX是一个重复组)OP说a最多有5个ReceptStrings此查询很好。从未使用过
regexp\u split\u to\u array
,但开始使用它看起来很酷。谢谢
 ITEMID     RECEPTSTRING1   RECEPTSTRING2   RECEPTSTRING3   RECEPTSTRING4  RECEPTSTRING5
 itemID1    receptString1   receptString2   receptString3   receptString4   
 itemID2    receptString5   receptString6