【问题标题】:How to return a single value built from values stored in multiple records?如何返回从存储在多个记录中的值构建的单个值?
【发布时间】:2019-09-03 23:14:00
【问题描述】:

不幸的是,我是一名应用程序开发人员,需要编写(/更新)SQL 语句以便为应用程序返回数据。我在 SQL 方面的经验有限,因此不胜感激。

我们有一个 Oracle 数据库 11g (11.2.0.4.0)

示例表

我创建了以下示例来复制我们的设置。它包括:

  • 一个包含不同城市旅行记录的主表。 (MAIN_TRIP_TABLE)
  • 各种附加表,其中包含通过 INNER JOIN 链接到这些行程的附加属性。 (ADDITIONAL_TABLE)
  • 一个单独的表格,显示沿途采取的步骤(即访问的临时地点)。 STEP_NUM = 1 的值始终是最终目的地,因此主表中每次行程在此表中始终至少有 1 条记录。如果旅程中有任何临时停靠点,它们将作为单独的记录列在此表中,STEP_NUM 向上迭代。 (JOURNEY_STEPS_TABLE

MAIN_TRIP_TABLE

RECORD_ID | PROP_1 | PROP_2 | FINAL_DEST | ...
-------------------------------------------------
10001     | A      | 1      | London     | ...
10002     | A      | 0      | Reading    | ...
10003     | B      | 1      | Leeds      | ...
10004     | B      | 0      | York       | ...

ADDITIONAL_TABLE

RECORD_ID | PROP_3 | ...
------------------------
10001     | X      | ...
10002     | Y      | ...
10003     | Y      | ...
10004     | X      | ...

JOURNEY_STEPS_TABLE

RECORD_ID | STEP_NUM | LOCATION | ...
--------------------------------------
10001     | 1        | London   | ...
10002     | 1        | Reading  | ...
10002     | 2        | Bath     | ...
10003     | 1        | Leeds    | ...
10003     | 2        | York     | ...
10003     | 3        | Bristol  | ...
10004     | 1        | York     | ...
10004     | 2        | Cardiff  | ...
10004     | 3        | Oxford   | ...
10004     | 4        | London   | ...

问题

我想检索类似的东西:

SELECT
  MAIN_TRIP_TABLE.RECORD_ID
, MAIN_TRIP_TABLE.PROP_1
, MAIN_TRIP_TABLE.PROP_2
, ADDITIONAL_TABLE.PROP_3
, <Concatenation/Array of JOURNEY_STEPS_TABLE> as "InterimStops"
FROM MAIN_TRIP_TABLE
INNER JOIN ADDITIONAL_TABLE ON MAIN_TRIP_TABLE.RECORD_ID = ADDITIONAL_TABLE.RECORD_ID
LEFT OUTER JOIN JOURNEY_STEPS_TABLE ON MAIN_TRIP_TABLE.RECORD_ID = JOURNEY_STEPS_TABLE.RECORD_ID

上面的“InterimStops”值是在 JOURNEY_STEPS_TABLE 中找到的任何和所有值的某种串联,对于特定的 RECORD_ID,按照 STEP_NUM 的递增顺序,使用某种分隔符。 (例如,对于 '10001' 我只想要 "London",对于 '10004' 我想要"York,Cardiff,Oxford,London")。

如果我得到这样的东西,我可以在我正在开发的应用程序中将它们分离到一个 JSON 数组中。

注意:实际的 SQL SELECT 查询与其他字段和表相比已经明显复杂得多,因此除非绝对必要,否则我希望避免将查询从 1 个 SELECT 查询(即,而不是使用多个查询)更改.

我尝试过的事情

经过一番谷歌搜索后,我开始使用 LISTAGG 构建 SQL 语句,开始时看起来很有希望:

SELECT
  MAIN_TRIP_TABLE.RECORD_ID
, LISTAGG(JOURNEY_STEPS_TABLE.LOCATION, ',') WITHIN GROUP (ORDER BY JOURNEY_STEPS_TABLE.STEP_NUMBER) "InterimStops"
FROM MAIN_TRIP_TABLE
LEFT OUTER JOIN JOURNEY_STEPS_TABLE ON MAIN_TRIP_TABLE.RECORD_ID = JOURNEY_STEPS_TABLE.RECORD_ID
GROUP BY MAIN_TRIP_TABLE.RECORD_ID

这完全返回了我正在寻找的那种值,但是当我尝试从主表和附加表(例如:MAIN_TRIP_TABLE.PROP_1、MAIN_TRIP_TABLE. PROP_2,ADDITIONAL_TABLE.PROP_3)。这给了我一个“ORA-00979: not a GROUP BY expression”错误。

然后我尝试通过子查询获取这些数据,但无法正常工作。

非常感谢任何帮助、洞察力或正确直接的指点。 非常感谢

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    使用子查询更容易做到这一点,因此您不必对连接的列集上的数据进行分组(正如您已经尝试过的那样):

    SELECT MAIN_TRIP_TABLE.RECORD_ID
         , (SELECT LISTAGG(JOURNEY_STEPS_TABLE.LOCATION, ',') WITHIN GROUP (ORDER BY JOURNEY_STEPS_TABLE.STEP_NUMBER) 
              FROM JOURNEY_STEPS_TABLE
             WHERE JOURNEY_STEPS_TABLE.RECORD_ID = MAIN_TRIP_TABLE.RECORD_ID) "InterimStops"
    FROM MAIN_TRIP_TABLE
    

    另一种可能性是LEFT JOIN分组数据:

    SELECT MAIN_TRIP_TABLE.RECORD_ID
         , JOURNEY_STEPS_TABLE."InterimStops"
      FROM MAIN_TRIP_TABLE
      LEFT JOIN (SELECT RECORD_ID
                      , LISTAGG(LOCATION, ',') WITHIN GROUP (ORDER BY STEP_NUMBER) "InterimStops"
                   FROM JOURNEY_STEPS_TABLE
                  GROUP BY RECORD_ID) JOURNEY_STEPS_TABLE
        ON JOURNEY_STEPS_TABLE.RECORD_ID = MAIN_TRIP_TABLE.RECORD_ID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      相关资源
      最近更新 更多