选择特定时间段内的所有可用项目

时间:2017-05-16 00:07:05

标签: mysql sql

所以我有2张桌子照顾和客户,就像这样

client {
  id,
  name
}

caring {
  id,
  startDate,
  endDate,
  clientId
}

我需要让所有在两个提供日期之间至少有一天可用的客户,您可以看到我的屏幕截图作为参考。

Screenshot

在屏幕截图中,我有两个客户端,我需要返回它们。如您所见,第一个客户在提供期间(16.5.-29.5。)之间有三个免费日(21.5.-23.5。),第二个客户没有任何关怀期。

到目前为止,我尝试过类似的事情

SELECT * FROM client cl
WHERE cl.id NOT IN (SELECT clientId FROM caring 
WHERE endDate >= CURDATE() AND endDate <= DATE_ADD(CURDATE(), INTERVAL 14 DAY))

这个只返回那些根本没有照顾的客户。这部分是我需要的,因为此查询不会覆盖我的屏幕截图中的第一个客户端。然后我尝试了下面的查询。

SELECT ca.startDate, ca.endDate, cl.firstName, cl.lastName
FROM caring ca
LEFT JOIN client cl on cl.id = ca.clientId
WHERE ca.startDate NOT IN (
    SELECT endDate
    FROM caring 
) AND ca.startDate <= '2017-05-29' AND ca.endDate >= '2017-05-16'

但我没有得到理想的结果。

任何想法我都能提前做到这一点!

2 个答案:

答案 0 :(得分:2)

在感兴趣的时段选择 carings ,并分别将开始/结束日期限制在此期间。此限制将允许更容易计算“已预订”,即稍后无法自由。

SELECT ca.id,
       -- Limit start/end dates to period of interest, respectively
       GREATEST (ca.startDate, '2017-05-16') AS `effectiveStartDate`,
       LEAST (ca.endDate, '2017-05-29') AS `effectiveEndDate`,
       ca.clientId
  FROM carings ca
 WHERE ca.startDate <= '2017-05-29' AND ca.endDate >= '2017-05-16';

接下来,计算预定天数:

DATEDIFF (DATE_ADD (LEAST (ca.endDate, '2017-05-29'), INTERVAL 1 DAY),
          GREATEST (ca.startDate, '2017-05-16'))
   AS `effectiveDays`

最后,过滤掉整个期间预订的客户。这是通过比较

来完成的
  • 每位客户的预订天数(GROUP BY)至
  • 整个期间的天数(HAVING sumDays < DATEDIFF(...))。

如果您还想要整个期间未预订的客户,我建议您从clients表开始,然后“只”LEFT JOIN(有效)carings

  SELECT cl.id, cl.name, IFNULL (SUM (eca.effectiveDays), 0) AS `sumDays`
    FROM clients cl
         LEFT JOIN
         (SELECT ca.id,
                 -- Limit start/end dates to period of interest, respectively
                 GREATEST (ca.startDate, '2017-05-16') AS `effectiveStartDate`,
                 LEAST (ca.endDate, '2017-05-29') AS `effectiveEndDate`,
                 DATEDIFF (
                    DATE_ADD (LEAST (ca.endDate, '2017-05-29'), INTERVAL 1 DAY),
                    GREATEST (ca.startDate, '2017-05-16'))
                    AS `effectiveDays`,
                 ca.clientId
            FROM carings ca
           WHERE ca.startDate <= '2017-05-29' AND ca.endDate >= '2017-05-16')
         eca                                               -- effectiveCarings
            ON eca.clientId = cl.id
GROUP BY cl.id, cl.name
  HAVING sumDays <
            DATEDIFF (DATE_ADD ('2017-05-29', INTERVAL 1 DAY), '2017-05-16')
ORDER BY cl.id;

另见http://sqlfiddle.com/#!9/1038b9/19

答案 1 :(得分:1)

选择endDate在您提供的期间的最后一天之前发生的客户,并且在指定期间内endDate和startDate之间存在差距。

SELECT * FROM client FULL OUTER JOIN caring ON client.id = caring.clientId WHERE endDate <= '2017-05-28' AND DATEDIFF(day, startDate, endDate) > DATEDIFF(day,  '2017-05-16' , endDate);