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

时间:2016-06-02 23:38:10

标签: symfony dql

我正在尝试将这个有效的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查询后的结果 - 例外!!!

[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();
    }

2 个答案:

答案 0 :(得分:2)

尝试在主查询周围使用双引号。我认为它看到&#34; \&#34;作为下一行并给出该错误。

更新了以下内容:

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();

再试一次!

答案 1 :(得分:0)

解决方案:

问题出现在(+ 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();
    }