有什么方法可以提供条件连接而不是
case when ... then ... end
?
我有 3 张桌子:
vehicles
、sport_cars
和 motorcycles
。
vehicles
- 存储 sport_cars
和 motorcycles
sprot_cars
- 包含跑车特定数据的表格motorcycles
- 包含摩托车特定数据的表格此外,
vehicles
有一个鉴别器列type
,其中包含varchar值sport_car
/motorcycle
。
示例模型:
车辆:
运动车:
摩托车:
我需要按类型检索所有车辆,并能够使用限制和偏移,使用单个查询,但无法找出它的方法。
select
r.id,
r.cost,
case
when :type = 'sport_car' then s.is_cabriolet
else m.is_motocross
end as flag
from (select
v.id,
v.cost,
v.sport_car_id,
v.motorcycle_id
from vehicles as v
where
v.type = :type
limit :limit
offset :offset) as r
left join sport_cars s on r.sport_car_id = s.id
left join motorcycles m on r.motorcycle_id = m.id
也许这个解决方案可行,但效果相当低,因为我们至少提供了一个奇数连接。另外,如果可以有多个表而不是 2 个,那么加入所有这些表将成为一场噩梦。
另外,我尝试使用
union all
检索它,但问题是为此类查询提供限制和偏移量会很棘手。
看起来,这可能是设计不好的问题,但这个模型已经存在,看起来不需要更新。
有什么办法可以为加入提供某种条件吗?或者也许有另一种方法来选择必要的数据?
您的数据库建模不正确。有几个裁员...
外键 sport_car_id 和 Motorola_id 不感兴趣。车辆表的主键必须作为子表的外键,同时作为主键
类型列不重要,因为它可以从连接中推导出来
正确的型号是:
CREATE TABLE vehicles
( id bigint PRIMARY KEY,
cost decimal(7,2) -- instead of number
);
CREATE TABLE sport_cars
( id bigint PRIMARY KEY REFERENCES vehicles (id),
is_cabriolet boolean,
seats integer
);
CREATE TABLE motorcycles
( id bigint PRIMARY KEY REFERENCES vehicles (id),
is_motocross boolean,
handlers integer
);
这在建模术语中称为继承...
这个模型必须通过触发器来完成,以确保排他性约束:车辆要么是摩托车,要么是汽车,换句话说,两个子表中永远不能有相同的 id 值....
这是这两个触发器之一:
CREATE FUNCTION sport_cars_id_exists()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
id_exists boolean;
BEGIN
SELECT (id IS NOT NULL) FROM sport_cars WHEREid = NEW.id INTO id_exists;
IF id_exists THEN
RAISE EXCEPTION 'Exclude exception between motorcycle and car (id : %)', NEW.id;
RETURN NULL;
END IF;
RETURN NEW;
END; $$;
CREATE TRIGGER EVT_IU_motorcycles
BEFORE INSERT OR UPDATE
ON motorcycles
FOR EACH STATEMENT EXECUTE PROCEDURE sport_cars_id_exists();
现在要知道车辆是摩托车还是汽车,您只需要知道连接是否存在于一个或另一个表中,如下所示:
SELECT *, CASE WHEN EXISTS(SELECT * FROM sport_cars AS c WHERE m.id = v.id)
THEN 'Sport Car'
EXISTS(SELECT * FROM motorcycles AS m WHERE m.id = v.id)
THEN 'Sport Car'
END AS vehicle_type
FROM vehicles AS v
这个查询应该是开发中系统使用的视图...