Коррелированные подзапросы всегда вызывают ошибку. Не могу понять, почему. - PullRequest
0 голосов
/ 03 августа 2020

Вот таблицы базы данных приложений

CREATE TABLE IF NOT EXISTS `Cars` (
  `car_id` int(11) NOT NULL AUTO_INCREMENT,
  `type` int(11) NOT NULL,
  `price` int(11) NOT NULL,
  `insertionDate` datetime NOT NULL,
  PRIMARY KEY (`car_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

 CREATE TABLE IF NOT EXISTS `newCars` (
  `car_id` int(11) NOT NULL, //Only new cars have a dealer (Cars.type = 1)
  `dealer_id` int(11) NOT NULL,
  PRIMARY KEY (`car_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `CarsPhotos` (
  `photo_id` int(11) NOT NULL AUTO_INCREMENT,
  `car_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `insertionDate` datetime NOT NULL,
  PRIMARY KEY (`photo_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE IF NOT EXISTS `Dealers` (
  `dealer_id` int(11) NOT NULL AUTO_INCREMENT,
  `dealerName` varchar(255) NOT NULL,
  `website` varchar(255) NOT NULL,
  `insertionDate` datetime NOT NULL,
  PRIMARY KEY (`dealer_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE IF NOT EXISTS `dealersPhotos` (
  `photo_id` int(11) NOT NULL AUTO_INCREMENT,
  `dealer_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `insertionDate` datetime NOT NULL,
  PRIMARY KEY (`photo_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Я пытаюсь найти автомобили, у которых есть хотя бы одна соответствующая фотография для просмотра (либо фотография автомобиля, либо фотография дилера) следующим образом:

  1. Поиск должен выполняться одним запросом
  2. Проверить, есть ли в машине хотя бы одна фотография carPhotosCount.
  3. if carPhotosCount = 0 Затем проверить, новая ли машина (Cars.type = 1)
  4. Если машина новая, то получите команду «iler_id »из таблицы newCars
  5. Проверьте, есть ли у дилера хотя бы один фотодилерPhotosCount.

Для этого у меня написал запрос SQL (MySQL) двумя способами, оба из них вызывают ошибку корреляции.

SELECT car_id ,
    FROM Cars c
    WHERE
      CASE
        WHEN
          (SELECT count(*) as carPhotosCount FROM CarsPhotos WHERE CarsPhotos.car_id = c.car_id HAVING carPhotosCount > 0) THEN 1
        ELSE
          CASE
            WHEN type = 1 THEN
              CASE
                WHEN
                  (SELECT count(*) as dealerPhotosCount FROM dealersPhotos
                  JOIN  newCars ON  newCars.car_id = c.car_id
                  WHERE dealersPhotos.dealer_id = newCars.dealer_id HAVING dealerPhotosCount > 0) THEN 1
                ELSE 0
              END
            ELSE 0
          END
      END

Запрос 2:

SELECT car_id ,
      CASE
        WHEN type = 1 THEN (SELECT newCars.dealer_id FROM newCars WHERE newCars.car_id = c.car_id)
        ELSE null
      END deal_id
    FROM Cars c
    WHERE
      CASE
        WHEN (SELECT count(*) as dealerPhotosCount FROM dealersPhotos WHERE dealersPhotos.dealer_id = deal_id HAVING dealerPhotosCount > 0) THEN 1
        ELSE
          CASE
            WHEN (SELECT count(*) as carPhotosCount FROM CarsPhotos WHERE CarsPhotos.car_id = c.car_id HAVING carPhotosCount > 0) THEN 1
            ELSE 0
          END
      END

1 Ответ

0 голосов
/ 03 августа 2020

Думаю, вам просто нужны exists и limit:

SELECT car_id ,
       (CASE WHEN type = 1
            THEN (SELECT nc.dealer_id FROM newCars nc WHERE nc.car_id = c.car_id LIMIT 1)
        END) as deal_id
FROM Cars c
WHERE EXISTS (SELECT 1
              FROM dealersPhotos dp
              WHERE dp.dealer_id = c.deal_id
             ) OR
      EXISTS (SELECT 1 
              FROM CarsPhotos cp
              WHERE cp.car_id = c.car_id
             ) ;

В запросах нет очевидной серьезной ошибки. Однако подзапрос в SELECT может возвращать более одной строки, и это обычно приводит к ошибке.

EDIT:

Кажется, вы хотите присоединиться к дилеру в внешний запрос, а затем включите logi c в предложение WHERE. Один из способов - повторить выражение в предложении WHERE:

SELECT c.car_id,
       (CASE WHEN c.type = 1 THEN nc.dealer_id END) as deal_id
FROM Cars c LEFT JOIN
     newCars nc
     ON nc.car_id = c.car_id 
WHERE EXISTS (SELECT 1
              FROM dealersPhotos dp
              WHERE dp.dealer_id = (CASE WHEN c.type = 1 THEN nc.dealer_id END)
             ) OR
      EXISTS (SELECT 1 
              FROM CarsPhotos cp
              WHERE cp.car_id = c.car_id
             ) ;
...