自定义表联接

时间:2018-10-02 13:35:06

标签: sql postgresql join

假设我在Postgresql DB中有4个表:

users {
 id: int
}

cars {
 id: int
}

usage_items {
 id: int,
 user_id: int,
 car_id: int,
 start: date,
 end: date
}

prices {
 id: int,
 car_id: int,
 price: int
}

当用户租车时,我正在创建一个usage_item记录来跟踪租车时间。在月底,我给他寄了一张计有费用的发票。 SQL非常简单:

SELECT usage_items.start, usage_items.end, prices.price
FROM usage_items
JOIN prices ON prices.car_id = usage_items.car_id

(我在这里省略了带有日期比较的WHERE子句,我在Ruby代码中进行了其余的计算)

我现在遇到的问题是我的一些用户与我签订了定制合同,以确保他们的价格更低。我正在寻找一种在数据库中表达这种逻辑的方法。 我想到了将user_id列添加到价格表的想法,但是这样,我将需要为每个用户创建价格。因此,我决定实施以下逻辑:如果prices行中的car_id为null,则意味着这是所有用户的默认价格。否则,它特定于用户。但是我不知道如何为这种情况编写SQL,因为:

SELECT usage_items.start, usage_items.end, prices.price
FROM usage_items
JOIN prices ON prices.car_id = usage_items.car_id
WHERE prices.user_id IS NULL OR prices.user_id = usage_items.user_id

返回两个价格的行。而且我只需要一个具有相关组的组,或者如果它不存在则具有一个空group_id的组。

您能帮我解决此SQL吗?还是我的设计不好,应该以某种方式更改它?

1 个答案:

答案 0 :(得分:2)

鉴于您现有的架构,这是完成所需目标的一种方法:

设置:

CREATE TABLE usage_items (user_id INTEGER, car_id INTEGER);
CREATE TABLE prices (user_id INTEGER, car_id INTEGER, price INTEGER);

INSERT INTO usage_items VALUES (1, 10), (2, 11), (3, 12);
INSERT INTO prices VALUES
    (1, 10, 101),
    (2, 11, 102),
    (4, 12, 104),
    (NULL, 10, 201),
    (NULL, 11, 202),
    (NULL, 12, 304);

查询(我没有使用开始/结束,但是是同一回事):

SELECT DISTINCT ON (u.user_id, u.car_id) u.user_id, u.car_id, p.price
FROM usage_items u
LEFT JOIN prices p
    ON u.car_id = p.car_id
    AND (u.user_id = p.user_id OR p.user_id IS NULL)
ORDER BY u.user_id, u.car_id, CASE WHEN p.user_id IS NOT NULL THEN 1 ELSE 2 END

结果:

| user_id | car_id | price |
| ------- | ------ | ----- |
| 1       | 10     | 101   |
| 2       | 11     | 102   |
| 3       | 12     | 304   |

如您所见,usage_items中的记录及其相应的汽车记录和prices中的user_id获得其自定义价格,而不是NULL版本;没有自定义价格的用户3获得NULL版本(而不是其他客户的自定义价格)。


在这里https://www.db-fiddle.com/f/wPVWEY3r22n22iKpDMrcMC/0