SQL 语句/Codeigniter 预约

Posted

技术标签:

【中文标题】SQL 语句/Codeigniter 预约【英文标题】:SQL Statement/ Codeigniter appointment booking 【发布时间】:2017-11-21 00:42:29 【问题描述】:

我正在开发一款带有日历的预订软件。我有四个表如下:

Services:
ID | EmployeeID| ServiceID| RoomID| StartDate        | EndDate
1  |     1     |     1    |   2   | 2017-06-18 01:00 |2017-06-18 02:00
2  |     2     |     1    |   1   | 2017-06-18 03:00 |2017-06-18 04:00

Employees: 
EmployeeID | Name
    1      |  A
    2      |  B
    3      |  C

Rooms:
RoomID | Name
  1    |  X
  2    |  Y
  3    |  Z

EmpBreaks: 
ID | EmployeeID | BreakStart       | BreakEnd
1  |     1      | 2017-06-18 02:00 | 2017-06-18 03:00

Services 表存储预约的详细信息,Employees 表包含所有员工的列表,Rooms 表包含所有房间的列表,EmpBreaks 存储员工不可用的所有时间。

我想执行查询以搜索指定开始和结束日期的所有可用员工和房间。

例如:

开始日期'2017-06-18 01:30' 结束日期 '2017-06-18 02:30'

结果:

员工 ID 3

房间 ID 1,3

这里是更新的工作代码。

function check_available_rooms_therapists() 
        $this->data['message'] = array();
        $this->data['success'] = FALSE;

    $post = $this->input->post();

    $EmployeeFields = array(
        'Employees.EmployeeID',
        'Employees.Name'
    );

    $sDate = $post['StartDate'];
    $eDate = $post['EndDate'];

    $whereEmp = "Employees.EmployeeID NOT IN (SELECT Services.EmployeeID FROM Services where 
        (( '" . $sDate . "' BETWEEN Services.StartDate AND Services.EndDate) or  
        ( '" . $eDate . "' BETWEEN Services.StartDate AND Services.EndDate) or
        (Services.StartDate BETWEEN '". $sDate ."' AND '" . $eDate ."') or
        (Services.EndDate BETWEEN '". $sDate ."' AND '" . $eDate ."')) union
        (SELECT EMPBREAKS.EMPID FROM EMPBREAKS WHERE(
        ('" . $sDate . "' BETWEEN EMPBREAKS.StartB AND EMPBREAKS.EndB) or 
        ('" . $eDate . "' BETWEEN EMPBREAKS.StartB AND EMPBREAKS.EndB) or 
        (EMPBREAKS.StartB BETWEEN '" . $eDate . "' AND '" . $sDate ."') or
        (EMPBREAKS.EndB BETWEEN '" . $eDate . "' AND '" . $sDate ."'))))";

    $this->db->select($EmployeeFields);
    $listing = $this->db->get_where('Employees', $whereEmp, 50 , 0);
    $result = $listing -> result();

    $avEmpName = array();
    $avEmpID = array();

    foreach ($result as $row) 
        $avEmpID[] = $row->EmployeeID;
        $avEmpName[] = $row->Name;
    

    $RoomFields = array(
        'Rooms.RoomID',
        'Rooms.Name'
    );

     $whereRoom = "Rooms.RoomID not in (SELECT Services.RoomID FROM Services WHERE 
        ((Services.startdate BETWEEN '" . $sDate . "' AND '" . $eDate. "') OR 
            (Services.enddate BETWEEN '" . $sDate . "' AND '" . $eDate. "') OR 
            ('" .$sDate . "' BETWEEN  Services.startdate AND Services.enddate) OR
            ('" .$eDate . "' BETWEEN  Services.startdate AND Services.enddate)))";

    $this->db->select($RoomFields);
    // $this->db->from('Rooms');
    $Rooms = $this->db->get_where('Rooms', $whereRoom, 50 ,0);
    $Rresult = $Rooms -> result();

    $avRoomName = array();
    $avRoomID = array();

    foreach ($Rresult as $r) 
        $avRoomID[] = $r->RoomID;
        $avRoomName[] = $r->Name;
    

        $this->data['EmployeeID'] =  $avEmpID;
        $this->data['RoomID'] = $avRoomID;
        $this->data['RoomName'] = $avRoomName;
        $this->data['Name'] = $avEmpName;

    $this->data['success'] = TRUE;
    echo json_encode($this->data);
    die;

【问题讨论】:

编辑您的问题并提供示例数据和所需的结果。 【参考方案1】:

也许您可以轻松地将问题拆分为两个不同的查询,

首先,您可以编写一个匹配您想要排除的所有内容的查询, 我们称之为错误结果, 之后,您可以从 EmployeeRooms 表中获取所有不在 错误结果中的员工和房间

select * from Employees
where Employees.EmployeeID not in (
SELECT a.EmployeeID
    FROM Appointments a
    where  ((a.startdate BETWEEN yourstartdate AND yourenddate ) or  (a.enddate BETWEEN yourstartdate AND yourenddate)));

select * from Rooms
where Rooms.RoomID not in (
    SELECT a.RoomID
    FROM Appointments a
    where  ((a.startdate BETWEEN yourstartdate AND yourenddate ) or  (a.enddate BETWEEN yourstartdate AND yourenddate)));

【讨论】:

我的问题似乎没有解释清楚。我已经更新了我的问题。我希望现在很清楚。 完美。正是我想要的。谢谢 不客气,抱歉,昨天在编辑之前有点难以理解您的问题!另一个建议您可以在子查询中使用 DISTINCT 谢谢。我使用有效的 sql 语句更新了我的问题中的代码,因为您提供的代码需要一些调整才能完全按照我的意愿工作。此外,我们需要检查 a.startdate BETWEEN yourstartdate AND yourenddate【参考方案2】:

工作 SQL 语句:

SELECT `Employees`.`EmployeeID`, `Employees`.`Name`
FROM (`Employees`)
WHERE `Employees`.`EmployeeID` NOT IN (SELECT Services.EmployeeID FROM Services where 
 (( yourstartdate BETWEEN Services.StartDate AND Services.EndDate) or 
 ( yourenddate BETWEEN Services.StartDate AND Services.EndDate) or
 (Services.StartDate BETWEEN yourstartdate AND yourenddate) or
 (Services.EndDate BETWEEN yourstartdate AND yourenddate)) union
 (SELECT EMPBREAKS.EMPID FROM EMPBREAKS WHERE(
 (yourstartdate BETWEEN EMPBREAKS.StartB AND EMPBREAKS.EndB) or 
 (yourenddate BETWEEN EMPBREAKS.StartB AND EMPBREAKS.EndB) or 
 (EMPBREAKS.StartB BETWEEN yourenddate AND yourstartdate) or
 (EMPBREAKS.EndB BETWEEN yourenddate AND yourstartdate))))

SELECT `Rooms`.`RoomID`, `Rooms`.`Name`
FROM (`Rooms`)
WHERE `Rooms`.`RoomID` not in (SELECT Services.RoomID FROM Services WHERE 
 ((Services.startdate BETWEEN 'yourstartdate AND yourenddate) OR 
 (Services.enddate BETWEEN 'yourstartdate AND yourenddate) OR 
 ('yourstartdate BETWEEN Services.startdate AND Services.enddate) OR
 (yourenddate BETWEEN Services.startdate AND Services.enddate)))

【讨论】:

以上是关于SQL 语句/Codeigniter 预约的主要内容,如果未能解决你的问题,请参考以下文章

1615 准备好的语句需要在codeigniter中重新准备

如何在 CodeIgniter 中使用准备好的语句

DB2请教取任何两个时间段内的所有年月的SQL语句如何实现 比如 20050903 -- 20060201,得到 200509 200510

我如何防止使用codeigniter进行sql注入[重复]

在codeigniter中逃避足够的防止sql注入的保护

使用 CodeIgniter Active Record 函数将子句添加到不带引号的 MySQL 语句