SQL OR NOT EXISTS 无效

SQL OR NOT EXISTS doesn't work

我有一个关于以下不起作用的查询的问题:

{thistable}.id IN (
SELECT id
FROM fab_booking_slots AS slots 
WHERE id = '{fab_booking___book_starttime_raw}'
OR NOT EXISTS (
SELECT id +1 FROM (
    SELECT taken.book_date, slots.*, count(taken.book_date) AS nbre 
    FROM fab_booking_taken AS taken 
    CROSS JOIN fab_booking_slots AS slots 
    WHERE NOT ((slots.heuredepart_resa < taken.book_end 
               AND slots.heurearrivee_resa > taken.book_start)) 
    AND DATE(taken.book_date) = DATE('{fab_booking___book_bookingdate}') 
    GROUP BY slots.id) AS x 
WHERE nbre = (
    SELECT count(taken.book_date) 
    FROM fab_booking_taken AS taken 
    WHERE taken.book_date = x.book_date)
    )
)
Order BY id ASC

此查询应 return 数据库中已存在的下拉列表中的值,如果它们是可用槽,则为可用槽。

当我 运行 2 SELECT 独立工作时,他们正在工作。

感谢这里的一些专业知识,因为我找不到原因而且我被困住了。

此主题跟在以下主题之后:

Whosebug

表格可以在那里下载。

提前感谢您的支持。

干杯,

马克

在这种情况下,我认为错误在于您使用 WHERE NOT EXISTS 的方式。如果您的子查询 return 没有行,这将 return true。通常,您与 EXISTSNOT EXISTS 一起使用的子查询将是一个 correlated subquery,它引用外部 select 中的列(在您的情况下为 fab_booking_slots),以便子查询 return 对外部 select 的每一行都有不同的结果。

因此,您可能已经知道足够多的理论(假设它是为未来的读者准备的),您在这里所做的是没有将子查询与外部引用相关联。由于您在外部查询和子查询中都使用了相同的 table 别名 slots,所以这很复杂。我会分配不同的别名以防止混淆。

我已经稍微简化了您的子查询中的逻辑,这应该仍然是 return 正确的结果。请注意,午夜后的时间有一个陷阱,因此我们需要通过在这些时间上增加一天来处理它们,然后比较才能正常进行:

{thistable}.id IN (
SELECT t.id
FROM fab_booking_slots AS t 
WHERE t.id = null
OR NOT EXISTS (
    Select 1 
    From  (Select book_date, 
           Convert(book_start, datetime) As book_start, 
           Case When book_end < '02:00:00' Then Date_Add(Convert(book_end, datetime), INTERVAL 1 DAY) Else Convert(book_end, datetime) End As book_end 
           From fab_booking_taken) AS p1
    Where Date(p1.book_date) = '2017-01-10'
    And Convert(p1.book_end, datetime) > Convert(t.heuredepart_resa, datetime)
    And Convert(p1.book_start, datetime) < Case When t.heurearrivee_resa < '02:00:00' Then Date_Add(Convert(t.heurearrivee_resa, datetime), INTERVAL 1 DAY) Else Convert(t.heurearrivee_resa, datetime) End
)
)
Order BY id ASC;