在SQL查询中运行检查(也许是子查询?)

时间:2018-10-23 09:48:11

标签: mysql sql

我有一个简单的笔记本电脑测试预订系统,其中包含6台笔记本电脑,名为Laptop01至06,每台笔记本电脑都分配了三个时隙。

如果未预订时段或预订已被取消/拒绝,则用户可以选择这些时段。

虽然我拥有有效的代码,但我已经意识到一个致命错误,该错误会导致取消/拒绝的广告位重复出现。

让我解释一下...

Database Design

  • 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,如下所示:

enter image description here

这使用户可以同时从两个插槽中进行选择,这意味着可以进行两次预订。

我现在知道使用Join是错误的事情,并且我假设我需要运行子查询,但是我不是SQL专家,并且希望获得一些帮助来查找类似“我可以从中学到的第二个查询。

如果我的术语错误,也表示歉意。

编辑:

根据要求,我包含了输出:

enter image description here

第二个编辑和结论:

最后,我设法通过一个子查询共同制定了一个解决方案,以在输出之前删除已取消/已拒绝的预订,然后使用“分组依据”仅显示每个时间之一。这很可能不是最好的方法,但是对我有用。

booked

感谢您的所有输入。

2 个答案:

答案 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)