【问题标题】:Alternative for union in OracleOracle 中联合的替代方案
【发布时间】:2016-06-29 11:00:57
【问题描述】:

有没有其他方法可以在不使用联合的情况下获取以下数据?

select A.name,A.age,B.Address,C.phoneNo from table1 A,Table2 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
union
select A.name,A.age,B.Address,C.phoneNo from table4 A,Table5 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId

我在 Hibernate 中使用它,不幸的是 hibernate 不支持 Union。我只是想知道是否有任何其他方法可以实现它,否则我必须在一个过程中编写它并将数据保存在临时表中并触发一个 sql 以从该临时表中读取数据

【问题讨论】:

  • 你能解释一下为什么你不想使用union吗?
  • UNION ALL 在这里可能更好?
  • 实际上我在 Hibernate 中使用它,不幸的是 hibernate 不支持 Union。我只是想知道是否有任何其他方法可以实现它,否则我必须在一个过程中编写它并将数据保存在临时表中并触发一个 sql 以从该临时表中读取数据
  • 为什么不创建查询视图并使用它?

标签: sql oracle


【解决方案1】:

union 有一个替代方案,但它并不漂亮:

select distinct coalesce(x1.name, x2.name) as name,
       coalesce(x1.age, x2.age) as age,
       coalesce(x1.Address, x2.Address) as age,
       coalesce(x1.phoneNo, x2.phoneNo) as age,
from (select A.name, A.age, B.Address, C.phoneNo
      from table1 A join
           Table2 B
           on a.pkId = b.FkId join
           Table3 C 
           on b.pkId = c.FkId
     ) x1 full outer join
     (select A.name, A.age, B.Address, C.phoneNo
      from table4 A join
           Table5 B
           on a.pkId = b.FkId join
           Table3 C 
           on b.pkId = c.FkId
     ) x2
     on 1 = 0;  -- always false

我无法想象你为什么要这样表达union。不过,我强烈建议您开始使用正确、明确的 join 语法。

【讨论】:

    【解决方案2】:

    这行得通吗?

    SELECT
        CASE DISTINCT_FLG WHEN 1 THEN nameA ELSE nameB END name,
        CASE DISTINCT_FLG WHEN 1 THEN ageA ELSE ageB END age,
        CASE DISTINCT_FLG WHEN 1 THEN AddressA ELSE AddressB END Address,
        CASE DISTINCT_FLG WHEN 1 THEN phoneNoA ELSE phoneNoB END phoneNo
    FROM (
        SELECT
            T1.name AS nameA, T1.age AS ageA, T2.Address AS AddressA, T3.phoneNo AS phoneNoA,
            T4.name AS nameB, T4.age AS ageB, T5.Address AS AddressB, T3.phoneNo AS phoneNoB,
            ROW_NUMBER() OVER(PARTITION BY T1.name, T1.age, T2.Address, T4.name, T4.age, T5.Address, T3.phoneNo ORDER BY NULL) AS DISTINCT_FLG
        FROM
            table1 T1,
            table2 T2,
            table4 T4,
            table5 T5,
            table3 T3
        WHERE
            T1.pkId = T2.FkId AND
            T4.pkId = T5.FkId AND
            (
                T2.pkId = T3.FkId OR
                T5.pkId = T3.FkId
            )
    ) WHERE DISTINCT_FLG IN (1, 2)
    

    【讨论】:

      【解决方案3】:

      这两个 UNION 部分有共同的Table3 C,所以我们可以加入其余部分。要模拟源表中的 UNION 记录,可以通过具有所需数量或行数的辅助表的无条件交叉连接来复制:

      Select Distinct
          CASE R.r WHEN 1 THEN A1.name    ELSE A2.name    END As name   ,
          CASE R.r WHEN 1 THEN A1.age     ELSE A2.age     END As age    ,
          CASE R.r WHEN 1 THEN B1.Address ELSE B2.Address END As Address,
          C.phoneNo
      From Table3 C,                                          --< Start at common Table3
        (Select Rownum r From USER_TABLES Where Rownum < 3) R --< Two rows to replicate Table3 C
      --   Any table with more than one row will do
      --   USER_TABLES should have enough rows in this particular case
      Left Join Table2 B1 On R.r = 1 AND B1.pkId = C.FkId     --< Left Join branch one
      Left Join table1 A1 On R.r = 1 AND A1.pkId = B1.FkId
      Left Join Table5 B2 On R.r = 2 AND B2.pkId = C.FkId     --< Left Join branch two
      Left Join table4 A2 On R.r = 2 AND A2.pkId = B2.FkId
      Where (R.r = 1 AND A1.pkId Is NOT NULL)                 --/ Make sure we have values
         OR (R.r = 2 AND A2.pkId Is NOT NULL)                 --\ for the branch
      

      但实际上,考虑view

      【讨论】:

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