简体   繁体   English

Mysql case join 查询辅助

[英]Mysql case join query assistance

I'm trying to create a query which gets all columns and a case column which denotes availablity, however I need to include a one to many relationship in the mix and it's messing with my head.我正在尝试创建一个查询,它获取所有列和一个表示可用性的 case 列,但是我需要在混合中包含一对多的关系,这让我很困惑。

My query without the relationship:我的查询没有关系:

SELECT storage_rooms.*,
    CASE
        WHEN release_date <= CURDATE() THEN 1
        WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
        ELSE 0 
    END AS available
FROM storage_rooms

Which is fine and returns something like this:这很好,并返回如下内容:

在此处输入图片说明

Now I need to check if it is already booked.现在我需要检查它是否已经被预订了。 To give you an idea of what I'm thinking (doesn't work):为了让您了解我在想什么(不起作用):

SELECT storage_rooms.*,
    (SELECT
    CASE
        WHEN release_date <= CURDATE() OR orders.status_id IN (3, 4) THEN 1
        WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
        ELSE 0 
    END AS available
    FROM storage_rooms
    LEFT OUTER JOIN orders
    ON storage_rooms.id = orders.storage_room_id)
FROM storage_rooms 

I gather I might need another subquery with a groupBy?我想我可能需要另一个带有 groupBy 的子查询? I don't find joins super intuitive and I'm a bit lost so any assistance would be welcome.我不觉得连接超级直观,我有点迷茫,所以欢迎任何帮助。

I'm not totally sure it will work but you can try this:我不完全确定它会起作用,但你可以试试这个:

SELECT storage_rooms.*,
    CASE
        WHEN release_date <= CURDATE() OR availibility.order_status_id IN (3, 4) THEN 1
        WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
        ELSE 0 
    END AS available
FROM storage_rooms
LEFT JOIN 
    ( SELECT id AS order_id, status_id AS order_status_id, storage_room_id AS order_storage_room_id
          FROM orders WHERE status_id IN (3, 4)
          GROUP BY storage_room_id
    ) availibility
    ON (storage_rooms.id = availibility.order_storage_room_id)

The thing here is that the LEFT JOIN is adding to the results the columns needed to check your availability.这里的问题是LEFT JOIN将检查可用性所需的列添加到结果中。 But the trick is you need a subquery so that the table joined contains only one entry for each room or else the results are duplicated.但诀窍是您需要一个子查询,以便连接的表只包含每个房间的一个条目,否则结果会重复。 The subquery must be limited to the positive matches you want to take in consideration with a WHERE , because the GROUP BY will only keep the first row found and you don't want this information lost in the grouping.子查询必须仅限于您要考虑使用WHERE的正匹配,因为GROUP BY只会保留找到的第一行,并且您不希望此信息在分组中丢失。

FROM OP'S COMMENTS THE FINAL QUERY IS:根据 OP 的评论,最终的问题是:

SELECT storage_rooms.*,
    CASE
        WHEN release_date <= CURDATE() OR aggregate.order_status_id IS NULL THEN 1
        WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
        ELSE 0
    END AS available
FROM storage_rooms
LEFT JOIN
    (SELECT storage_room_id, order_status_id
        FROM orders WHERE order_status_id IN (1, 2)
        GROUP BY storage_room_id, order_status_id
    ) aggregate
    ON storage_rooms.id = aggregate.storage_room_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM