我正在创建一个将被许多客户端应用程序使用的数据库(使用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
,x
和y
。我不希望客户端必须构造该查询。我宁愿让他们做更类似的事情:
z
当然,我可以为SELECT * FROM a_view WHERE b_type = x AND c_type = y AND d_type = z
,x
和y
的每种可能组合创建一个视图,但这会是很多观点。有没有更好的方法来解决这个问题,或者我应该放弃并让客户使用z
编写查询?
答案 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