创建一个视图,允许您向LEFT JOIN ... ON添加条件?

时间:2015-11-13 15:51:38

标签: sql oracle left-join sql-view

我正在创建一个将被许多客户端应用程序使用的数据库(使用Oracle 12c)。为了简化,我尝试通过创建不同的视图在数据库中保留尽可能多的逻辑,这样客户端就可以在没有Q_FOREACH (QPair<int, int> p, pairList) JOIN等更复杂的结构的情况下提出简单的问题。他们应该只需要在视图中执行一个简单GROUP BY条件SELECT,并让视图完成繁重的工作。

现在我的问题是我想在表格上提问

WHERE

从客户端输入SELECT -- Some fields. FROM a LEFT JOIN b ON a.id = b.id AND b.type = x LEFT JOIN c ON a.id = c.id AND c.type = y LEFT JOIN d ON a.id = d.id AND d.type = z xy。我不希望客户端必须构造该查询。我宁愿让他们做更类似的事情:

z

当然,我可以为SELECT * FROM a_view WHERE b_type = x AND c_type = y AND d_type = z xy的每种可能组合创建一个视图,但这会是很多观点。有没有更好的方法来解决这个问题,或者我应该放弃并让客户使用z编写查询?

2 个答案:

答案 0 :(得分:2)

这可以完成,但您必须拥有所有有效类型的源,并假设用户/应用程序仅查询有效类型的视图。换句话说,假设表T是你的“类型表”,你的所有B,C和D表都有(或可能有)在T上定义的FK。

在这种情况下,你的视图def。将是:

CREATE OR REPLACE VIEW V AS
SELECT A.ID, BT.TYPE BTYPE, CT.TYPE CTYPE, DT.DTYPE DTYPE, ... 
FROM A 
CROSS JOIN T BT
CROSS JOIN T CT
CROSS JOIN T DT
LEFT JOIN B ON A.ID = B.ID AND B.TYPE = BT.TYPE
LEFT JOIN C ON A.ID = C.ID AND C.TYPE = CT.TYPE
LEFT JOIN D ON A.ID = D.ID AND D.TYPE = DT.TYPE;

当然,如果模型中有一组固定的有效类型,您可以用(SELECT 'X' TYPE FROM DUAL UNION ALL SELECT 'Y' FROM DUAL UNION ALL ...)替换T

唯一区别:

SELECT
    -- Some fields.
FROM a
LEFT JOIN b ON a.id = b.id AND b.type = x
LEFT JOIN c ON a.id = c.id AND c.type = y
LEFT JOIN d ON a.id = d.id AND d.type = z

SELECT * FROM V WHERE B_TYPE = X AND C_TYPE = Y AND D_TYPE = Z

如果X,Y或Z不是“有效”类型(在这种情况下,视图def。将不返回任何行)。

编辑:澄清每条评论;我假设“类型”是表B,C和D的公共域。如果B.type与C.type不同(即B.TYPE是NUMERIC(9)而C.type是VARCHAR(2)并且D.TYPE是NUMERIC(1))然后交叉连接需要独立地引用每个“有效类型值集”:

CREATE OR REPLACE VIEW V AS
SELECT A.ID, BT.TYPE BTYPE, CT.TYPE CTYPE, DT.DTYPE DTYPE, ... 
FROM A 
CROSS JOIN (--SELECT ALL DISTINCT VALID B.TYPE VALUES--) BT
CROSS JOIN (--SELECT ALL DISTINCT VALID C.TYPE VALUES--) CT
CROSS JOIN (--SELECT ALL DISTINCT VALID D.TYPE VALUES--) DT
LEFT JOIN B ON A.ID = B.ID AND B.TYPE = BT.TYPE
LEFT JOIN C ON A.ID = C.ID AND C.TYPE = CT.TYPE
LEFT JOIN D ON A.ID = D.ID AND D.TYPE = DT.TYPE;

那就是说,你有相同的限制:内置于视图def。必须是“所有有效B类型”,“所有有效C类型”和“所有有效D类型”的某些有限来源。除此之外,这在纯SQL中是不可行的(实际上,就纯SQL而言,它变成了一个棘手的问题 - 支持通过任何可能的值组合进行过滤的视图,没有过滤器,应返回所有可能的值组合。 ..)

答案 1 :(得分:0)

可能您可以使用“旧式连接语法”:

SELECT
    -- Some fields.
FROM a, b, c, d
WHERE a.id = b.id(+) AND b.type(+) = x
  AND a.id = c.id(+) AND c.type(+) = y
  AND a.id = d.id(+) AND d.type(+) = z

例如:

SQL> with
     t  as (select rownum r from dual connect by level < 6),
     t1 as (select rownum r from dual connect by level < 5),
     t2 as (select rownum r from dual connect by level < 4)
select *
  from t, t1, t2
 where t.r = t1.r(+) and t1.r(+) = 3
   and t.r = t2.r(+) and t2.r(+) = 2
order by 1, 2, 3;

     R      R          R
---------- ---------- ----------
     1
     2             2
     3      3
     4
     5