【问题标题】:Combining data from multiple records into multiple columns of a single record in SQL将多条记录中的数据组合成SQL中单条记录的多列
【发布时间】:2018-08-06 03:20:07
【问题描述】:

请在下面找到我的表结构和测试数据。

CREATE TABLE TX(
  TX_ID  VARCHAR2(10),
  DESCRIPTION  VARCHAR2(100),
  CONSTRAINT "PK_TX" PRIMARY KEY ("TX_ID")
);

CREATE TABLE PARTNER(
  TX_ID  VARCHAR2(10),
  PTNR_ID  VARCHAR2(10),
  PTNR_NAME VARCHAR2(50),
  PTNR_TYPE VARCHAR2(20),
  CONSTRAINT "PK_TX_PARTNER" PRIMARY KEY ("TX_ID", "PTNR_ID"),
  CONSTRAINT "FK_TX_PARTNER" FOREIGN KEY ("TX_ID") REFERENCES TX("TX_ID") ON DELETE CASCADE ENABLE
);

INSERT INTO TX VALUES('1','Transaction 1');
INSERT INTO TX VALUES('2','Transaction 2');
INSERT INTO TX VALUES('3','Transaction 3');
INSERT INTO TX VALUES('4','Transaction 4');
INSERT INTO TX VALUES('5','Transaction 5');

INSERT INTO PARTNER VALUES('1','P1', 'Partner 1', 'Exporter');
INSERT INTO PARTNER VALUES('1','P2', 'Partner 2', 'Importer');
INSERT INTO PARTNER VALUES('1','P3', 'Partner 3', 'Supplier');
INSERT INTO PARTNER VALUES('2','P1', 'Partner 1', 'Exporter');
INSERT INTO PARTNER VALUES('2','P2', 'Partner 2', 'Importer');

现在,我需要检查与每笔交易相关的合作伙伴详细信息并将其显示在一条记录中。输出应该是这样的。

TX_ID | DESCRIPTION    | PTNR_ID_1 | PTNR_NAME_1 | PTNR_ID_2 | PTNR_NAME_2 | PTNR_ID_3 | PTNR_NAME_3
----------------------------------------------------------------------------------------------------
1     | Transaction 1  | P1        | Partner 1   | P2        | Partner 2   | P3        | Partner 3
2     | Transaction 2  | P1        | Partner 1   | P2        | Partner 2

通过下面的 SQL 查询,我可以得到我正在寻找的结果。但我正在寻找更好的方法来实现这一目标。

SELECT 
  T.TX_ID AS "TRANSACTION ID",
  T.DESCRIPTION AS "DESCRIPTION", 
  P1.PTNR_ID AS "EXPORTER ID", 
  P1.PTNR_NAME AS "EXPORTER NAME",
  P2.PTNR_ID AS "IMPORTER ID", 
  P2.PTNR_NAME AS "IMPORTER NAME",
  P3.PTNR_ID AS "SUPPLIER ID", 
  P3.PTNR_NAME AS "SUPPLIER NAME"
FROM 
  TX T
  LEFT OUTER JOIN PARTNER P1 ON (T.TX_ID = P1.TX_ID) AND P1.PTNR_TYPE='Exporter'
  LEFT OUTER JOIN PARTNER P2 ON (T.TX_ID = P2.TX_ID) AND P2.PTNR_TYPE='Importer'
  LEFT OUTER JOIN PARTNER P3 ON (T.TX_ID = P3.TX_ID) AND P3.PTNR_TYPE='Supplier';

编辑: 我尝试了内部查询和案例组合,如下所述。它没有以所需的方式返回数据。我收到重复的记录。对于不同的合作伙伴类型,产生了不同的记录。我不确定如何合并这些结果。

SELECT DISTINCT TRANSACTION_ID, DESCRIPTION, EXPORTER_ID, EXPORTER_NAME, IMPORTER_ID, IMPORTER_NAME, SUPPLIER_ID, SUPPLIER_NAME
FROM (
        SELECT 
          T.TX_ID AS "TRANSACTION_ID",
          T.DESCRIPTION AS "DESCRIPTION", 
          (CASE WHEN P1.PTNR_TYPE = 'Exporter' THEN P1.PTNR_ID ELSE NULL END) AS "EXPORTER_ID", 
          (CASE WHEN P1.PTNR_TYPE = 'Exporter' THEN P1.PTNR_NAME ELSE NULL END) AS "EXPORTER_NAME",
          (CASE WHEN P1.PTNR_TYPE = 'Importer' THEN P1.PTNR_ID ELSE NULL END) AS "IMPORTER_ID", 
          (CASE WHEN P1.PTNR_TYPE = 'Importer' THEN P1.PTNR_NAME ELSE NULL END) AS "IMPORTER_NAME",
          (CASE WHEN P1.PTNR_TYPE = 'Supplier' THEN P1.PTNR_ID ELSE NULL END) AS "SUPPLIER_ID", 
          (CASE WHEN P1.PTNR_TYPE = 'Supplier' THEN P1.PTNR_NAME ELSE NULL END) AS "SUPPLIER_NAME"
        FROM 
          TX T
          INNER JOIN PARTNER P1 ON (T.TX_ID = P1.TX_ID) AND P1.PTNR_TYPE= ANY('Exporter', 'Importer', 'Supplier')
);

另外,我正在寻找 Oracle SQL 解决方案,但不是 PL/SQL 解决方案。我可以使用 BEGIN...END 块,但不能使用游标。

【问题讨论】:

  • 哪个 dbms?????
  • @Eric,我正在寻找 Oracle SQL 中的解决方案。

标签: sql oracle performance join merging-data


【解决方案1】:

如果您可以将合作伙伴信息作为单个列而不是单独的列,请尝试使用 Oracle 称为 LISTAGG 的“分析功能”:

select a.tx_id,
       a.description,
       sub.result
  from tx a,
       (select b.tx_id,
               listagg('<' || b.ptnr_id || ' ' || b.ptnr_name || '>', ' ')
                within group (order by b.ptnr_id) as result
          from partner b
          group by b.tx_id
         ) sub
 where a.tx_id = sub.tx_id

【讨论】:

  • 感谢您的建议。但是,我需要不同列中的数据。
  • 您在每行返回“0 或 1 或 20 或...”合作伙伴时遇到问题。如果您打算插入结果甚至显示结果,SQL 需要知道一行中的列数。直接 SQL 不会轻易地为每一行搜索任意数量的列。 PL/SQL 可以使用可以增长到几乎任何大小的“NESTED TABLE”(嗯,实际上不是无限的,但对合作伙伴有实际限制)。 NESTED TABLE 甚至可以按原样存储在表中。但是您表示您不想处理高级 PL/SQL(COLLECTIONs、CURSORs 等)。我没有也不是动态的“简单”解决方案。
  • 这是我创建的一个示例,用于解决我正在处理的一个非常大的查询。我想澄清一下,我的要求中的列数不会改变。现在,让我们说,我想在这个查询中只显示“出口商”和“进口商”。将来,如果我还需要添加“供应商”信息,我将添加这些列并相应地进行更改。简而言之,对于给定的场景/查询,列没有增长。你现在有什么解决办法吗?
  • 如果数据规则限制每个合作伙伴 id 为 1 个“类型”(“进口商”、“出口商”、“供应商”等),您可以使用更静态的 SQL。您在表描述中没有任何此类限制,因此“许多返回列”的概率仍然存在。数据模型是否以这种方式受到限制?
  • 是的,每种合作伙伴类型有 1 个合作伙伴 ID。甚至,我已经准备好将合作伙伴类型添加到复合主键中,以便更好地说明。
【解决方案2】:

你可以用不同的方式来写,试试这个方法。请改用inner join

SELECT 
  T.TX_ID AS "TRANSACTION ID",
  T.DESCRIPTION AS "DESCRIPTION", 
  (select PTNR_ID from partner where PTNR_TYPE='Exporter' )AS "EXPORTER ID", 
  (select PTNR_NAME from partner where PTNR_TYPE='Exporter' ) AS "EXPORTER NAME",
  (select PTNR_ID from partner where PTNR_TYPE='Importer' ) AS "IMPORTER ID", 
  (select PTNR_NAME from partner where PTNR_TYPE='Importer' ) AS "IMPORTER NAME",
  (select PTNR_ID from partner where PTNR_TYPE='Supplier' ) AS "SUPPLIER ID", 
   (select PTNR_NAME from partner where PTNR_TYPE='Supplier' )    AS "SUPPLIER NAME"
FROM 
  TX T
  inner join partner p on p.tx_id = t.tx_id

【讨论】:

  • @B House,这行不通。在子查询中,没有到 TX 表的链接,所以每个子查询都会返回多行。
猜你喜欢
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 2016-02-06
  • 1970-01-01
相关资源
最近更新 更多