【问题标题】:Oracle sql,plsql create a sql building up the variablesOracle sql,plsql 创建一个构建变量的 sql
【发布时间】:2019-03-21 00:35:16
【问题描述】:

想知道是否有人可以指导我正确的方向。

我的数据表结构如下:

table2_type char (1)

table2_key char (40)

table2_reftype char (20)

table2_seq char (10)

table2_ref char (50)

和数据行类似(逗号分隔仅供阅读):

I,123456789,typea,0000000001,abc

I,123456789,typeb,0000000002,999

I,123456789,typec,0000000003,9z9

I,123456789,typed,0000000004,zyx

I,123456789,typee,0000000005,qwe

I,987654321,typea,0000000006,bcd

I,987654321,typeb,0000000007,444

我现在必须做的是获取相同 table_key 值的所有 table_ref 值(为便于阅读而间隔):

select table1_bkey,

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typea',20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typea',20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad('typea',20)) end),' ') as REF_A,

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typeb',20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typeb',20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad('typeb',20)) end),' ') as REF_B,

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typec',20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typec',20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad('typec',20)) end),' ') as REF_C,

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typed',20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typed',20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad('typed',20)) end),' ') as REF_D,

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typee',20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad('typee',20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad('typee',20)) end),' ') as REF_E

from table1 where table1_bkey = '123456789';

我目前每个 table2_key 最多可以有 25 个不同的 table2_reftype,所以我必须做 25 个 case 语句。如果/当添加新的 table2_reftype 时,我必须做新的案例陈述。

我的问题是,有没有一种方法可以获取每个 table2_key 的所有 table2_reftype 值,而无需执行多个 case 语句,例如:

仅供说明之用,请勿以任何方式将文字视为代码!!

while table2_key = table1_bkey

get table2_reftype 

then for each table2_reftype 

nvl((case when (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad(<table2_reftype variable>,20)) is not null then (select table2_ref from table2 where table2_key = table1_bkey and table2_reftype = rpad(<table2_reftype variable>,20)) else (select table2_ref from table2 where table2_key = table1_alt and table2_reftype = rpad(<table2_reftype variable>,20)) end),' ') as REF_<table2_reftype  variable>

where table1_bkey = '123456789';

第一次发帖,希望我已经提供了足够的信息。

【问题讨论】:

  • 顺便问一下,您确定要将所有char 值空白填充到最大值吗?似乎是一个奇怪的业务需求。
  • 嗨,在我找到问题的解决方案之前,我必须做些什么。

标签: sql oracle


【解决方案1】:

我认为你可以使用这样的东西:

select key, ref_a, ref_b, ref_c
  from (
    select table1_bkey key, table2_ref ref, trim(table2_reftype) type, 
           row_number() over (partition by table1_bkey, table2_reftype 
                              order by case table2_key when table1_bkey then 1 else 2 end) rn
      from table1
      left join table2 
        on trim(table2_reftype) in ('typea', 'typeb', 'typec')
        and table2_key in (table1_bkey, table1_alt))
  pivot (max(ref) for type in ('typea' ref_a, 'typeb' ref_b, 'typec' ref_c))
  where rn = 1

dbfiddle demo

这里发生了什么?我使用您的条件left join-ed 两个表。然后我分配了rn,这取决于匹配是在基本键还是备用键上完成。 Base 具有更高的优先级,因此如果两者都被发现,则删除第二个 (where rn = 1)。休息很容易,只需为您硬编码的类型提供数据。另请注意,我修剪了ref_type。

这是 3 种类型的示例,当您添加新类型时,只需将其放在两个列表中即可。正如您在我的 dbfiddle 查询中看到的那样,但我不得不想象一些您没有描述的数据(对于 table1)。

如果出现问题并且您无法更正/调整此解决方案,请编辑您的问题并以工作 create 和 insert 语句的形式为两个表提供示例数据,并向我们展示所需的结果这个数据。

您也可以像在伪代码中描述的那样解决它,但这需要动态 PLSQL,或者在其他代码中构造查询(我在 .NET 中做了类似的事情)。为什么?因为 Oracle 在编译查询时必须知道所有列。

我希望这会有所帮助:)

【讨论】:

  • 您好,感谢您的回复。我将尝试您的查询,维护我当前的 sql 绝对更简单。我试图消除的一件事是维护 sql 中的 table2_reftype 并找到添加新的时可以处理的代码,也许就像你说的那样,plsql 但我不确定如何实现这一点。跨度>
  • 您好,再次表示感谢。我让查询运行。我只做了 1 处更改:在 ('typea', 'typeb', 'typec') 中的 trim(table2_reftype) 上:在 table2_type = 'I' 和 table2_reftype 上 (select distinct(table2_reftype) from table2 where table2_type = 'I' and table2_key in (table1_bkey, table1_alt)) 这消除了需要维护的区域之一。只需要找到一个可以对枢轴部分执行类似操作的解决方案。
  • 这是我写的。不幸的是,您不能使枢轴部分在选择上工作。它必须具有硬编码的列。在旧的 Oracle 版本中,我们必须做类似的事情,分别对每一列进行硬编码。 SO上有很多关于动态枢轴的问题,你可以看看它们,但没有什么令人满意的、简单的、开箱即用的。我做了一次回答,我在动态 SQL 中创建了view,你也许可以使用它,但这是解决方法。 Oracle 必须知道它的列。
  • 嗨思考。我是新来的,我试图找到你的文章,但没有任何乐趣。我点击了你的名字,找到了你已经回答的文章,但我在动态 sql one 中找不到视图。有链接吗?
  • 是的。链接1,链接2。请记住,当您动态创建 view 所有使用它的依赖 Oracle 对象时,可能需要重新验证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-17
  • 2018-08-15
相关资源
最近更新 更多