我有一个简单的笔记本电脑测试预订系统,其中包含6台笔记本电脑,名为Laptop01至06,每台笔记本电脑都分配了三个时隙。
如果未预订时段或预订已被取消/拒绝,则用户可以选择这些时段。
虽然我拥有有效的代码,但我已经意识到一个致命错误,该错误会导致取消/拒绝的广告位重复出现。
让我解释一下...
event_information
-保存预订事件信息(仅ID为
此示例所需)event_machine_time
-包含所有
笔记本电脑,每台笔记本电脑三行,并提供独特的计时
可供选择event_booking
-保留实际的预订
然后链接到另一个候选数据库,不在此处然后我运行一个简单的查询,将所有内容连接在一起,并且(我认为)可以确定预订的事件:
SELECT machine_laptop, machine_name, B.id AS m_id, C.id AS c_id, C.confirmed AS c_confirmed, C.live AS c_live,
(C.id IS NOT NULL AND C.confirmed !=2 AND C.live !=0) AS booked
FROM event_information A
INNER JOIN event_machine_time B ON ( 1 =1 )
LEFT JOIN event_booking C on (B.id = C.machine_time_id and A.id = C.information_id )
WHERE A.id = :id
ORDER BY `B`.`id` DESC
booked
正在检查confirmed
是否不是2-这意味着预订已被取消/拒绝(0-未确认,1-已确认),而live
正在检查删除(0-已删除,1-未删除)。
但是,如果某个人被删除(live
-0)或取消/拒绝(confirmed
-2),那么在我的前端插槽选择器下拉菜单中,它将添加一个额外的插槽,作为{{ 1}}列仍为0,如下所示:
这使用户可以同时从两个插槽中进行选择,这意味着可以进行两次预订。
我现在知道使用Join是错误的事情,并且我假设我需要运行子查询,但是我不是SQL专家,并且希望获得一些帮助来查找类似“我可以从中学到的第二个查询。
如果我的术语错误,也表示歉意。
编辑:
根据要求,我包含了输出:
第二个编辑和结论:
最后,我设法通过一个子查询共同制定了一个解决方案,以在输出之前删除已取消/已拒绝的预订,然后使用“分组依据”仅显示每个时间之一。这很可能不是最好的方法,但是对我有用。
booked
感谢您的所有输入。
答案 0 :(得分:0)
尝试以下方法:
SELECT machine_laptop, machine_name, B.id AS m_id, C.id AS c_id, C.confirmed
AS c_confirmed, C.live AS c_live,
(C.id IS NOT NULL AND C.confirmed !=2 AND C.live !=0) AS booked
FROM event_information A
LEFT JOIN event_booking C ON A.id = C.information_id
RIGHT JOIN event_machine_time B ON B.id = C.machine_time_id
WHERE A.id = :id
ORDER BY `B`.`id` DESC
答案 1 :(得分:0)
如果将event_booking(B)作为查询的起点,则可以看到不需要使用从A和C提取所有行和列的方式。Intead可以直接加入匹配的行。但由于我什至无法正确掌握您的查询要实现的目标,因此我首先要提出几个问题:
尽管这可能起作用,但实际上它不在您的控制范围内,也不由您定义。一些更严格的模式会礼貌地告诉您在SELECT中指定要引用的别名表,
SELECT machine_laptop, machine_name -- combined with
FROM event_information A
实际上是没有意义的,它起作用的唯一原因是您正在利用MySQL的优化。除此之外,您还尝试以混合模式进行表联接(这意味着您同时使用JOIN和WHERE tA.colX = tB.colY方法。这确实很难遵循。
INNER JOIN event_machine_time B ON ( 1 =1 )
嗯?这到底是什么目的?据我所知,这只会导致它联接两个完整的表,只是稍后使用WHERE过滤结果。
此外,您是否还在使用主键?您的条件包括 C.id IS NOT NULL ,而主键甚至不能包含NULL(因为NULL是SQL领域中的第三个布尔状态。有True,False和Null(表示未定义,这显然是不能在主键中使用,因为主键必须是唯一的,并且Undefined值可以是任何值或什么都不是-这样做违反了唯一性要求。)因此,我假设您实际上正在使用此NULL检查,因为临时表在加入似乎包含它们?
编辑: 尝试将其分为两部分,首先连接2个表,然后将第3个表与结果连接。
我建议您简要浏览What is the difference between "INNER JOIN" and "OUTER JOIN"?-因为这是一篇很棒的文章,并阐明了许多方面。
首先,我会选择类似的东西:
SELECT
<i.cols>,
<b.cols>,
<mt.cols>,
IF(b.confirmed !=2 AND b.live !=0, True, False) sa booked
FROM
event_booking b
LEFT JOIN
event_information i ON b.information_id = i.id
LEFT JOIN
event_machine_time mt ON b.machine_time_id = mt.id
WHERE <conditions>
稍后,我将LEFT JOIN更改为更合适的名称。但是请记住,仅当您100%确定从联接表列返回的行是唯一的时,INNER JOIN才有用。
i和b表之间甚至可以存在1:n,n:1的关系吗?我假设不能对同一事件信息(n:1)进行多次预订,也不能对多个事件都使用相同的事件信息? (1:n)