使用SQL连接确定何时可用

时间:2014-05-25 19:41:33

标签: mysql sql

我有一些关于产品和服务的数据以及它们的日期和不可用的日期。我希望能够生成在任何指定日期可用的产品列表。

我所假设的数据默认情况下产品始终可用,但可以通过指定它们在特定日期范围内不可用或者它们仅在特定日期范围内可用来限制其可用性。

我遇到的问题是前一种情况;我无法找到一种方法来使用连接来指定如果产品在任何NOT条目的日期范围内,则它不应出现在结果中。我无法找到正确解释这一点的词语,所以最好用简化的例子说明......

产品表:

ID,Name
0,Apples  
1,Bananas  
2,Carrots  
3,Dates  
4,Eggs  

限制表:

ID,Product_ID,Type,Start,End
0,2,Only,2014-05-20,2014-05-31  
1,2,Only,2014-07-01,2014-07-14  
2,3,Not,2014-03-05,2014-04-04  
3,3,Not,2014-04-29,2014-06-15

预期结果的示例:

Date: 2014-01-01  
Products available: Apples, Bananas, Dates, Eggs  

Date: 2014-04-04  
Products available: Apples, Bananas, Eggs

Date: 2014-05-25  
Products available: Apples, Bananas, Carrots, Eggs  

Date: 2014-07-02  
Products available: Apples, Bananas, Carrots, Dates, Eggs  

我目前尝试使用左连接:

SELECT *  
FROM Product LEFT JOIN Restriction ON Product.ID = Restriction.ProductID  
WHERE  
    (
        Restriction.Type = 'Only'
        AND DATEDIFF(Restriction.Start, '2014-04-04') <= 0
        AND DATEDIFF(Restriction.End, '2014-04-04') >= 0
    )
    OR
    (
        Restriction.Type = 'Not'
        AND
        (
            DATEDIFF(Restriction.Start, '2014-04-04') > 0
            OR
            DATEDIFF(Restriction.End, '2014-04-04') < 0
        )
    )
    OR Restriction.Type IS NULL

以上查询的输出:

Product.ID,Product.Name,Restriction.Product_ID,Restriction.Type,Restriction.Start,Restriction.End  
0,Apples,-,-,-,-,-
1,Bananas,-,-,-,-,-
3,Dates,3,3,Not,2014-04-29,2014-06-15
4,Eggs,-,-,-,-,-

如你所见,&#34;日期&#34;仍然出现在结果中,因为虽然省略了它与限制#2的连接,但它与限制#3的连接不是。我无法找到任何方法来改变查询来解决这个问题,而不会以其他方式破坏逻辑。我希望我在这里有意义,并且有人可以看到我目前失明的任何洞察力。

我使用的数据库软件是MySQL 5.5。

1 个答案:

答案 0 :(得分:2)

首先获取限制表中now() 可用的内容(您可以将其更改为您喜欢的任何日期)

select *
  from restriction
 where (type = 'Not' and now() between start and end)
    or (type = 'Only' and now() not between start and end);

现在将该部分设为left outer join并使用从连接中获取null的所有行

select *
  from products p
  left outer join (select *
                     from restriction
                    where (type = 'Not' and now() between start and end)
                       or (type = 'Only' and now() not between start and end)) r
                on (p.id = r.product_id)
 where r.product_id is null;