【问题标题】:create oracle view based on comparision of data between two database tables根据两个数据库表之间的数据比较创建oracle视图
【发布时间】:2021-01-08 13:57:20
【问题描述】:

我有以下表格:

  • 我想创建视图,以便对于两个表中的descr = 'O' 和常见的id_isin 字段值,检查ratio 字段并只取ratio 字段值较低的行。
  • 对于descr = 'O',如果 id_isin 存在于一个表中但不存在于另一个表中,则取这些行(双向)
  • 对于descr ! = 'O' 所在的所有行,从表IS_ID_TST 中获取所有这些行。

以下是视图的预期输出,例如:

ID_ISIN   QUOTE_CRNY   DESCR           RATIO              ALLOCATIONASSETTYPE
L000123    USD              O              0.0769          Other total
L000129    USD              O              0.0669          Other total
D123458    USD              O              0.64039         Other total
M123456    USD              O              5.64039         Other total
F563458    USD              C              0.84039         Other total
G123456    USD              null           0.04039         Other total
L000123    USD              C              5.0769          Other total

我可以根据这个条件创建视图吗?

【问题讨论】:

  • IS_ID_TST 表的插入语句有问题?你能检查并纠正它吗?
  • 您的脚本甚至不起作用。在表 IS_ID_TST 中,您将 FUND_QUOTE_CRNY 定义为 NUMBER(19,8)。但是您尝试插入的值是'USD',导致“ORA-01722:无效号码”
  • 我已经更正了脚本并测试了它,它现在应该可以工作了
  • 对于点for member_descr = 'O' and if the fund_isin exist in one table but not in another then take those rows .......(1)。从IS_IDIS_ID_TST 是单向的还是双向的?..(2)。为什么fund_isin = D123458 只有一行采用低比率 bing 但根据逻辑两者都应该存在于输出中,因为它确实存在于IS_ID 但不存在于IS_ID_TST 中?
  • @Sujit 我已经创建了新问题,并在您的答案下方发表了评论stackoverflow.com/questions/64044272/…

标签: sql oracle select view


【解决方案1】:

您需要 LEAST() 函数以及 3 个子查询以及 UNION 子句。其中两个子查询应在表中包含FULL JOIN

CREATE VIEW V_MEMBER_FUND AS    
SELECT i.fund_isin,
       i.member_descr,
       LEAST(i.member_ratio, t.member_ratio) AS member_ratio,
       i.allocationassettype
  FROM IS_ID i
  JOIN IS_ID_TST t
    ON t.fund_isin = i.fund_isin
   AND t.member_descr = i.member_descr
 WHERE i.member_descr = 'O'
UNION
SELECT LEAST(NVL(i.fund_isin,t.fund_isin),NVL(t.fund_isin,i.fund_isin)) AS fund_isin,
       LEAST(NVL(i.member_descr,t.member_descr),NVL(t.member_descr,i.member_descr)) AS member_descr,
       LEAST(NVL(i.member_ratio,t.member_ratio),NVL(t.member_ratio,i.member_ratio)) AS member_ratio,
       LEAST(NVL(i.allocationassettype,t.allocationassettype),NVL(t.allocationassettype,i.allocationassettype)) AS allocationassettype
  FROM IS_ID i
  FULL JOIN IS_ID_TST t
    ON t.fund_isin = i.fund_isin
 WHERE (i.member_descr = 'O' OR t.member_descr = 'O' )
   AND ( t.fund_isin IS NULL OR i.fund_isin IS NULL )
UNION
SELECT t.fund_isin,
       t.member_descr,
       t.member_ratio,
       t.allocationassettype
  FROM IS_ID i
 RIGHT JOIN IS_ID_TST t
    ON t.fund_isin = i.fund_isin
   AND t.member_descr = i.member_descr
 WHERE (NVL(i.member_descr,'XYZ') != 'O' OR NVL(t.member_descr,'XYZ') != 'O' )
   AND t.fund_isin IS NOT NULL  

对于第一种情况:只需要返回与i.member_descr = 'O'匹配的member_ratio的最小值。

对于第二种情况:告知需要双向(FULL JOIN) 逻辑

对于第三种情况:需要一个与IS_ID_TST 表(在当前情况下为RIGHT JOIN)的位置相对应的外部联接以及非member_desct'O' 的等效值(即使是 NULL 值也应该被消除,并为此目的添加 NVL() 函数

并且在这三种情况下指定的所有子查询都应与UNION 组合,以提供逐行组合,包括消除重复行。

Demo

【讨论】:

  • 如果您可以评论逻辑的某些部分,谢谢您可能会非常有帮助..特别是在您为我提到的 3 点编写逻辑的地方...
  • 不客气@Symonds,我已经添加了更多解释。
  • 对不起,我想稍作改动,但我认为它与当前逻辑相矛盾...... IS_ID_TST 表中有fund_isin for member_descr = 'O' for which member_ratio
  • 最初对于fund_isin,我们仅在member_descr = 'O' 的情况下从IS_ID 表中获取数据,但是当member_ratio 较低时,我们需要从IS_ID 表中获取所有数据,对于此类fund_isin,它不应从IS_ID_TST 中获取数据表检查输出fund_isin L000123,D123458 ...我认为这里的逻辑会矛盾,因为最后逻辑是从IS_ID_TST表中获取所有数据,其中member_descr! = 'O' 否则两个表中会出现相同 FUND_ISIN 的重复项?对于所有其他情况,我们应该从 IS_ID_TST 表 M123456、F563458、G123456 中获取数据
  • 确定我已经创建了问题stackoverflow.com/questions/64044272/… 谢谢
【解决方案2】:

我提出了以下查询,请检查我已将 cmets 放在查询中。询问是否不符合您的要求或进行任何澄清。

CREATE VIEW v_combined_data AS
WITH combined_data
AS
(
SELECT t1.fund_isin
      ,t1.fund_quote_crny
      ,t1.member_descr
      ,t1.member_ratio
      ,t1.allocationassettype
      ,t2.fund_isin fund_isin_tst
      ,t2.fund_quote_crny fund_quote_crny_tst
      ,t2.member_descr member_descr_tst
      ,t2.member_ratio member_ratio_tst
      ,t2.allocationassettype allocationassettype_tst
FROM   is_id t1
FULL   OUTER JOIN is_id_tst t2
ON     t1.fund_isin = t2.fund_isin
AND    t1.fund_quote_crny = t2.fund_quote_crny
AND    t1.member_descr = t2.member_descr
)
-- for member_descr = 'O' and for common fund_isin field value from both tables, 
-- check the member_ratio field and take only the row where member_ratio field value is low.
SELECT d.fund_isin
      ,d.fund_quote_crny
      ,d.member_descr
      ,LEAST(d.member_ratio,d.member_ratio_tst) member_ratio
      ,d.allocationassettype
  FROM combined_data d
WHERE d.member_descr = 'O'
  AND d.fund_isin IS NOT NULL 
  AND d.fund_isin_tst IS NOT NULL
UNION ALL
--for member_descr = 'O' and if the fund_isin exist in one table but not in another then take those rows(bidirectional)
--exists in IS_ID and not in IS_ID_TST
SELECT d.fund_isin
      ,d.fund_quote_crny
      ,d.member_descr
      ,d.member_ratio
      ,d.allocationassettype
  FROM combined_data d
WHERE d.member_descr = 'O'
  AND NOT EXISTS (SELECT 1
                    FROM combined_data ci
                   WHERE ci.fund_isin_tst = d.fund_isin
                     AND ci.fund_quote_crny_tst = d.fund_quote_crny
                     AND ci.member_descr_tst = 'O')
UNION ALL
--for member_descr = 'O' and if the fund_isin exist in one table but not in another then take those rows(bidirectional)
--exists in IS_ID_TST and not in IS_ID
SELECT d.fund_isin_tst
      ,d.fund_quote_crny_tst
      ,d.member_descr_tst
      ,d.member_ratio_tst
      ,d.allocationassettype_tst
  FROM combined_data d
WHERE d.member_descr_tst = 'O'
  AND NOT EXISTS (SELECT 1
                    FROM combined_data ci
                   WHERE ci.fund_isin = d.fund_isin_tst
                     AND ci.fund_quote_crny = d.fund_quote_crny_tst
                     AND ci.member_descr = 'O')
UNION ALL
--for all the rows where member_descr ! = 'O', take all those rows from table IS_ID_TST
SELECT d.fund_isin_tst
      ,d.fund_quote_crny_tst
      ,d.member_descr_tst
      ,d.member_ratio_tst
      ,d.allocationassettype_tst
  FROM combined_data d
WHERE d.fund_isin_tst IS NOT NULL
  AND (d.member_descr_tst != 'O' OR d.member_descr_tst IS NULL);

【讨论】:

  • @Symonds,只需在查询顶部添加 create view view_name as ....然后我将进行编辑。等等..
  • 非常感谢这似乎有效..如果有任何问题我会发表评论:)
  • 不客气。是的,当然,我会尽力回答:)
  • 在完全外连接中也不能应用 member_descr = 'O' 的过滤器,这可以提高性能?
  • @Symonds,是的,我们可以这样做,但是您需要将最后一个联合更改为实际表并相应地过滤O以外的值
猜你喜欢
  • 2021-01-10
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 2017-06-19
相关资源
最近更新 更多