【问题标题】:Oracle display value replacement of flattened, delimited foreign key valuesOracle 显示替换扁平、分隔的外键值的值
【发布时间】:2015-09-14 21:51:38
【问题描述】:

我正在为一个令人痛苦的非规范化 COTS 产品进行数据导出,并且对如何在包含外键分隔字符串的列的选择中插入显示值感到困惑。

假设以下数据集为例。

部门表:

Key   Value
---------------------------------
1     Finance
2     Human Resources
3     Public Affairs
4     Information Technology

人员表:

PK    FName    LName    Departments
-------------------------------------------------
111   Marty    Graw     1|~*~|3|~*~|
222   Rick     Shaw     2|~*~|4|~*~|
333   Jean     Poole    4|~*~|2|~*~|3|~*~|1|~*~|

选择的期望输出:

FName    LName    Departments
-----------------------------------------------------------------------------------
Marty    Graw     Finance, Public Affairs
Rick     Shaw     Human Resources, Information Technology
Jean     Poole    Information Technology, Human Resources, Public Affairs, Finance

我找到了如何处理分隔字符串的示例,但似乎没有什么真正适合这种特殊情况。理想情况下,我想弄清楚如何在不必创建函数等的情况下做到这一点,因为我的权限非常有限。

【问题讨论】:

  • 部门名称的列出顺序是否与部门列中 ID 的列出顺序不同有关系吗?
  • 这是一种存储外键的可怕方式。你真的不应该那样做。为什么不正确规范化你的数据模型,然后这个查询就变成了一个简单的连接。
  • @a_horse_with_no_name 我完全同意!不幸的是,这是一个供应商 (COTS) 应用程序,其数据库设计不佳。他们几乎所有的数据完整性都依赖于应用程序。整个数据库中没有一个外键约束!简直太可笑了!
  • @a_horse_with_no_name,当他们已经在第一句话中承认问题并声明他们不对糟糕的设计负责时,责备 OP 的糟糕设计是没有帮助的。在现实世界。我们必须一直处理次优设计,有时“从头开始重新设计”并不是客户的最佳选择。
  • @JeffreyKemp:我不同意。保持这样的设计几乎总是最糟糕的选择。因为我不知道什么是 COTS 产品(从未听说过那家公司),所以我不知道这不是一个本土解决方案。

标签: oracle foreign-keys csv


【解决方案1】:

这不会保留 ID 的原始顺序,但如果这不重要,那么这将起作用:

select DISTINCT
       p.fname
      ,p.name
      ,LISTAGG(d.value, ', ')
       WITHIN GROUP (ORDER BY d.value)
       OVER (PARTITION BY p.pk)
       AS departments_list
from personnel p
left join departments d
on INSTR('|~*~|'||p.departments||'|~*~|'
        ,'|~*~|'||d.key||'|~*~|') > 0;

SQL 小提琴:http://sqlfiddle.com/#!4/d292e/3/0

编辑

如果您确实需要按照与 ID 相同的顺序列出它们,您可以使用此变体:

select DISTINCT
       p.fname
      ,p.lname
      ,LISTAGG(d.value, ', ')
       WITHIN GROUP (
         ORDER BY INSTR('|~*~|'||p.departments||'|~*~|'
                       ,'|~*~|'||d.key||'|~*~|'))
       OVER (PARTITION BY p.pk) AS departments_list
from personnel p
left join departments d
on INSTR('|~*~|'||p.departments||'|~*~|'
        ,'|~*~|'||d.key||'|~*~|') > 0;

http://sqlfiddle.com/#!4/d292e/4

【讨论】:

  • 谢谢 Jeffery,这将完美运行!您一定会喜欢尝试支持设计不佳的供应商应用程序!
  • 昨晚刚刚意识到,如果您确实需要按 ID 列表顺序排序的名称,您可以按 INSTR 的结果进行排序。已更新。
  • 很好的发现。这可能会派上用场。再次感谢!很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
相关资源
最近更新 更多