将包含具有三个参数的 MySQL CONCAT 函数的查询转换为 DQL 查询(两个参数)

Converting query including MySQL CONCAT function with three parameters to DQL Query (two parameters)

我正在尝试将此工作 MySQL 查询转换为 DQL 查询,但我在使用 DQL 中的 CONCAT 函数(可能)时遇到了问题。据我所知,DQL 中的 CONCAT 函数只能接受 两个参数 ,但我需要三个参数,搜索后我找到了这个解决方案 - NESTED CONCAT

MySQL 需要转换为 DQL 的查询:

SET @new_booking_pickup_date = '2016-04-01';
SET @new_booking_pickup_time = '12:00:00';
SET @new_booking_return_date = '2016-05-01';
SET @new_booking_return_time = '13:00:00';

SELECT * FROM Reservation WHERE NOT ( 

CONCAT(@new_booking_pickup_date,' ',@new_booking_pickup_time) > CONCAT(return_date,' ',return_time) + INTERVAL 0 DAY 
OR 
CONCAT(@new_booking_return_date,' ',@new_booking_return_time) < CONCAT(pickup_date,' ',pickup_time) + INTERVAL 0 DAY
);

这是我正在尝试的 DQL 解决方案 NESTED CONCAT:

return $this->getEntityManager()
    ->createQuery(
        'SELECT id, licensePlate,

        (SELECT car1.model FROM AppBundle:Car car1 WHERE car1.id = car.id) AS model_id,
        (SELECT car2.brand FROM AppBundle:Car car2 WHERE car2.id = car.id) AS brand_id,

        (SELECT carmodel.model FROM AppBundle:CarModel carmodel WHERE carmodel.id = model_id) AS model_name,
        (SELECT carbrand.brand FROM AppBundle:CarBrand carbrand WHERE carbrand.id = brand_id) AS brand_name

          FROM AppBundle:Car car WHERE IDENTITY(car.id) NOT IN (

            SELECT IDENTITY(reservation.car) FROM AppBundle:Reservation reservation WHERE NOT (

              CONCAT(CONCAT(:pickupDate, \' \'),:pickupTime) > CONCAT(CONCAT(reservation.returnDate, \' \'),reservation.returnTime) + INTERVAL 0 DAY 
           OR 
              CONCAT(CONCAT(:returnDate, \' \'),:returnTime) < CONCAT(CONCAT(reservation.pickupDate, \' \'),reservation.pickupTime) + INTERVAL 0 DAY

           )


           )'
    )
    ->setParameter('pickupDate', $pickupDate)
    ->setParameter('returnDate', $returnDate)
    ->setParameter('returnTime', $returnTime)
    ->setParameter('pickupTime', $pickupTime)
    ->getResult();

这是执行 DQL 查询后的结果 - Exception!!!:

[Syntax Error] line 0, col 831: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '0' 

编辑:根据@Alvin Bunk 的提议尝试了这个 DQL 查询但没有成功:

return $this->getEntityManager()
        ->createQuery(
            "SELECT car.id AS car_id,

            (SELECT IDENTITY(car1.model) FROM AppBundle:Car car1 WHERE car1.id = car.id) AS model_id,
            (SELECT IDENTITY(car2.brand) FROM AppBundle:Car car2 WHERE car2.id = car.id) AS brand_id,

            (SELECT carmodel.model FROM AppBundle:CarModel carmodel WHERE carmodel.id = model_id) AS model_name,
            (SELECT carbrand.brand FROM AppBundle:CarBrand carbrand WHERE carbrand.id = brand_id) AS brand_name

              FROM AppBundle:Car car WHERE IDENTITY(car.id) NOT IN (

                SELECT IDENTITY(reservation.car) FROM AppBundle:Reservation reservation WHERE NOT (

                  CONCAT(CONCAT(:pickupDate,' '),:pickupTime) > CONCAT(CONCAT(reservation.returnDate,' '),reservation.returnTime) + INTERVAL 0 DAY 
               OR 
                  CONCAT(CONCAT(:returnDate,' '),:returnTime) < CONCAT(CONCAT(reservation.pickupDate,' '),reservation.pickupTime) + INTERVAL 0 DAY

               )


               )"
        )
        ->setParameter('pickupDate', $pickupDate)
        ->setParameter('returnDate', $returnDate)
        ->setParameter('returnTime', $returnTime)
        ->setParameter('pickupTime', $pickupTime)
        ->getResult();

这里我在主查询周围使用双引号,在 CONCAT 函数中使用单引号。我收到相同的错误消息:

[Syntax Error] line 0, col 849: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '0' 

编辑: 我开始认为问题出在 NESTED CONCAT 函数,但我在控制台中对其进行了测试,它运行良好 - 结果如下:

php app/console doctrine:query:dql "SELECT CONCAT(CONCAT(car.licensePlate,' '),car.deposit) FROM AppBundle:Car car"

array(4) {
  [0]=>
  array(1) {
    [1]=>
    string(10) "B0001HA 20"
  }
  [1]=>
  array(1) {
    [1]=>
    string(10) "B0002HA 20"
  }
  [2]=>
  array(1) {
    [1]=>
    string(10) "B0003HA 30"
  }
  [3]=>
  array(1) {
    [1]=>
    string(10) "B0004HA 40"
  }
}

解决方法:

问题出在 (+ INTERVAL 0 DAY) - DQL 不支持它,在这种情况下我什至不需要它,因为我的字段已经是 DATE 和 TIME 类型。

public function getCarsNotInRange($pickupDate, $pickupTime, $returnDate, $returnTime)
    {
        return $this->getEntityManager()
            ->createQuery(
                "
                SELECT car.id, car.licensePlate,

                (SELECT IDENTITY(car1.model) FROM AppBundle:Car car1 WHERE car1.id = car.id) AS model_id,
                (SELECT IDENTITY(car2.brand) FROM AppBundle:Car car2 WHERE car2.id = car.id) AS brand_id,

                (SELECT carmodel.model FROM AppBundle:CarModel carmodel WHERE carmodel.id = model_id) AS model_name,
                (SELECT carbrand.brand FROM AppBundle:CarBrand carbrand WHERE carbrand.id = brand_id) AS brand_name

                  FROM AppBundle:Car car WHERE car.id NOT IN 
                  (
                    SELECT IDENTITY(reservation.car) FROM AppBundle:Reservation reservation WHERE NOT 
                        (
                          CONCAT(CONCAT(:pickupDate, ' '),:pickupTime) > CONCAT(CONCAT(reservation.returnDate, ' '),reservation.returnTime)
                     OR 
                          CONCAT(CONCAT(:returnDate, ' '),:returnTime) < CONCAT(CONCAT(reservation.pickupDate, ' '),reservation.pickupTime)
                      )
                  )

        ")
            ->setParameter('pickupDate', $pickupDate)
            ->setParameter('returnDate', $returnDate)
            ->setParameter('returnTime', $returnTime)
            ->setParameter('pickupTime', $pickupTime)
            ->getResult();
    }

尝试在主查询周围使用双引号。我认为它会将“\”视为下一行并给出该错误。

更新了以下内容:

return $this->getEntityManager()
    ->createQuery(
        "SELECT id, licensePlate,
        (SELECT car1.model FROM AppBundle:Car car1 WHERE car1.id = car.id) AS model_id,
        (SELECT car2.brand FROM AppBundle:Car car2 WHERE car2.id = car.id) AS brand_id,
        (SELECT carmodel.model FROM AppBundle:CarModel carmodel WHERE carmodel.id = model_id) AS model_name,
        (SELECT carbrand.brand FROM AppBundle:CarBrand carbrand WHERE carbrand.id = brand_id) AS brand_name
        FROM AppBundle:Car car
          WHERE IDENTITY(car.id) NOT IN (
            SELECT IDENTITY(reservation.car) FROM AppBundle:Reservation reservation WHERE NOT (
              CONCAT(:pickupDate, \' \', :pickupTime) > CONCAT(reservation.returnDate, \' \', reservation.returnTime) + INTERVAL 0 DAY 
           OR 
              CONCAT(:returnDate, \' \',:returnTime) < CONCAT(reservation.pickupDate, \' \',reservation.pickupTime) + INTERVAL 0 DAY
           )
           )"
    )
    ->setParameter('pickupDate', $pickupDate)
    ->setParameter('returnDate', $returnDate)
    ->setParameter('returnTime', $returnTime)
    ->setParameter('pickupTime', $pickupTime)
    ->getResult();

再试一次!

解决方法:

问题出在 (+ INTERVAL 0 DAY) - DQL 不支持它,在这种情况下我什至不需要它,因为我的字段已经是 DATE 和 TIME 类型。

public function getCarsNotInRange($pickupDate, $pickupTime, $returnDate, $returnTime)
    {
        return $this->getEntityManager()
            ->createQuery(
                "
                SELECT car.id, car.licensePlate,

                (SELECT IDENTITY(car1.model) FROM AppBundle:Car car1 WHERE car1.id = car.id) AS model_id,
                (SELECT IDENTITY(car2.brand) FROM AppBundle:Car car2 WHERE car2.id = car.id) AS brand_id,

                (SELECT carmodel.model FROM AppBundle:CarModel carmodel WHERE carmodel.id = model_id) AS model_name,
                (SELECT carbrand.brand FROM AppBundle:CarBrand carbrand WHERE carbrand.id = brand_id) AS brand_name

                  FROM AppBundle:Car car WHERE car.id NOT IN 
                  (
                    SELECT IDENTITY(reservation.car) FROM AppBundle:Reservation reservation WHERE NOT 
                        (
                          CONCAT(CONCAT(:pickupDate, ' '),:pickupTime) > CONCAT(CONCAT(reservation.returnDate, ' '),reservation.returnTime)
                     OR 
                          CONCAT(CONCAT(:returnDate, ' '),:returnTime) < CONCAT(CONCAT(reservation.pickupDate, ' '),reservation.pickupTime)
                      )
                  )

        ")
            ->setParameter('pickupDate', $pickupDate)
            ->setParameter('returnDate', $returnDate)
            ->setParameter('returnTime', $returnTime)
            ->setParameter('pickupTime', $pickupTime)
            ->getResult();
    }