【问题标题】:Transpose a table result dynamically动态转置表格结果
【发布时间】:2020-04-01 12:00:57
【问题描述】:

很抱歉,但我想知道如何做到这一点。 我正在尝试转换一张桌子,但我不得不说实话:我不知道该怎么做

使用我的查询:

SELECT vu.fly
      ,tg.FININ fecha_ini
      ,td.BA33_DESC place
      ,tms.tms_util.getplazas_singuiachofer(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) as passengers
FROM TABLE(fnc_obtener_vuelos_guia(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO)) vu
    inner join tms.gui tg on (tg.fol = vu.fol and tg.prod = vu.producto and tg.FININ = vu.fecha_inicio)
    inner join tms.dgp td on (tg.fol = td.fol and tg.prod = td.prod)
where td.fol = :P10_FOLLETO
      and td.prod = :P10_PRODUCTO
      and tg.FININ = :P10_FECHA_INICIO

下一个结果:

但我想得到这个:

有人可以帮我解决这个问题,因为这真的很重要。只是说记录/列的数量将是动态的,可以是一个或多个

问候

非常感谢

【问题讨论】:

  • 不要使用图片。在问题中将数据显示为文本表格

标签: sql oracle plsql oracle-apex


【解决方案1】:

您可以使用条件聚合。但是你需要一个序列来分配它。目前尚不清楚您如何指定排序,因此按字母顺序按fly

select fecha_ini, place, passengers,
       max(case when seqnum = 1 then fly end) as fly_1,
       max(case when seqnum = 2 then fly end) as fly_2,
       max(case when seqnum = 3 then fly end) as fly_3,
       max(case when seqnum = 4 then fly end) as fly_4
from (select vu.fly, tg.FININ as fecha_ini, td.BA33_DESC as place,
             tms.tms_util.getplazas_singuiachofer(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) as passengers,
             row_number() over (partition by tg.FININ, td.BA33_DESC order by vu.fly) as seqnum
      from TABLE(fnc_obtener_vuelos_guia(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO)) vu join
           tms.gui tg
           on tg.fol = vu.fol and
              tg.prod = vu.producto and 
              tg.FININ = vu.fecha_inicio join
           tms.dgp td
           on tg.fol = td.fol and
              tg.prod = td.prod
      where td.fol = :P10_FOLLETO and
            td.prod = :P10_PRODUCTO and
            tg.FININ = :P10_FECHA_INICIO
     ) f
group by fecha_ini, place, passengers;

如果您有另一列来指定排序,则将其用于order by

编辑:

您可能会发现只需聚合数据并为所有fly 值使用一个字符串就足够了:

select fecha_ini, place, passengers,
       list_agg(fly, ', ') within group (order by fly) as flys
from (select vu.fly, tg.FININ as fecha_ini, td.BA33_DESC as place,
             tms.tms_util.getplazas_singuiachofer(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) as passengers
      from TABLE(fnc_obtener_vuelos_guia(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO)) vu join
           tms.gui tg
           on tg.fol = vu.fol and
              tg.prod = vu.producto and 
              tg.FININ = vu.fecha_inicio join
           tms.dgp td
           on tg.fol = td.fol and
              tg.prod = td.prod
      where td.fol = :P10_FOLLETO and
            td.prod = :P10_PRODUCTO and
            tg.FININ = :P10_FECHA_INICIO
     ) f
group by fecha_ini, place, passengers;

【讨论】:

  • 你好@Gordon 这个查询看起来不错,但是我怎么说,如果我有 4 条记录,或者 2 或 6 条……你知道吗?它怎么可能是动态的?问候
  • @Julio 。 . .那将是一个不同的问题,需要使用 Oracle 脚本语言 pl/sql。
【解决方案2】:

您可以按如下方式使用 row_number。但是我要明确一点,纯SQL方案会生成静态列数,如果要生成动态列数则需要使用PL/SQL方案。

使用PIVOT的SQL解决方案:

SELECT * FROM
(SELECT vu.fly
      ,tg.FININ fecha_ini
      ,td.BA33_DESC place
      ,tms.tms_util.getplazas_singuiachofer(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) as passengers
      ,row_number() over (partition by tg.FININ, td.BA33_DESC order by vu.fly) as rn
FROM TABLE(fnc_obtener_vuelos_guia(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO)) vu
    inner join tms.gui tg on (tg.fol = vu.fol and tg.prod = vu.producto and tg.FININ = vu.fecha_inicio)
    inner join tms.dgp td on (tg.fol = td.fol and tg.prod = td.prod)
where td.fol = :P10_FOLLETO
      and td.prod = :P10_PRODUCTO
      and tg.FININ = :P10_FECHA_INICIO)
) 
PIVOT (MAX(fly) for rn in (1,2,3,4));

--更新--

您可以使用匿名块填充光标,然后打印如下。在您的应用程序中,您可以创建过程并返回光标。

SET SERVEROUT ON
DECLARE 
P_OUT_CUR SYS_REFCURSOR;
BEGIN
    OPEN P_OUT_CUR FOR 'SELECT * FROM
        (SELECT vu.fly
              ,tg.FININ fecha_ini
              ,td.BA33_DESC place
              ,tms.tms_util.getplazas_singuiachofer(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) as passengers
              ,row_number() over (partition by tg.FININ, td.BA33_DESC order by vu.fly) as rn
        FROM TABLE(fnc_obtener_vuelos_guia(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO)) vu
            inner join tms.gui tg on (tg.fol = vu.fol and tg.prod = vu.producto and tg.FININ = vu.fecha_inicio)
            inner join tms.dgp td on (tg.fol = td.fol and tg.prod = td.prod)
        where td.fol = :P10_FOLLETO
              and td.prod = :P10_PRODUCTO
              and tg.FININ = :P10_FECHA_INICIO) 
        PIVOT (MAX(fly) for rn in ('
                       || (
        SELECT
            LISTAGG(RN, ',') WITHIN GROUP(
                ORDER BY
                    RN
            )
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER(
                        PARTITION BY TG.FININ, TD.BA33_DESC
                        ORDER BY
                            VU.FLY
                    ) AS RN
                FROM
                    TABLE ( FNC_OBTENER_VUELOS_GUIA(:P10_FOLLETO, :P10_PRODUCTO, :P10_FECHA_INICIO) ) VU
                    INNER JOIN TMS.GUI TG ON ( TG.FOL = VU.FOL
                                               AND TG.PROD = VU.PRODUCTO
                                               AND TG.FININ = VU.FECHA_INICIO )
                    INNER JOIN TMS.DGP TD ON ( TG.FOL = TD.FOL
                                               AND TG.PROD = TD.PROD )
                WHERE
                    TD.FOL = :P10_FOLLETO
                    AND TD.PROD = :P10_PRODUCTO
                    AND TG.FININ = :P10_FECHA_INICIO
            )
    )
                       || '))'
        USING P10_FOLLETO, P10_PRODUCTO, P10_FECHA_INICIO, P10_FOLLETO, P10_PRODUCTO, P10_FECHA_INICIO, P10_FOLLETO, P10_PRODUCTO
        , P10_FECHA_INICIO;

dbms_sql.return_result(P_OUT_CUR); -- JUST TO PRINT THE RESULT OF THE CURSOR

END;
/

此代码未经测试,因此如果您发现愚蠢的错误,则需要更正代码。

【讨论】:

  • plsql 怎么能动态地做到这一点,因为这是我遇到的问题,我可以有 1、2、4 或 10 条记录。问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
相关资源
最近更新 更多