Соединение SQL, которое отображает левую таблицу, даже если правая таблица не совпадает с

0

У меня есть 2 таблицы, определенные как таковые:

CREATE TABLE `product` (
`pid` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR( 50 ) NOT NULL,
`description` TEXT,
`qty` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0',
`category` ENUM( '1', '2', '3', '4', '5', '6', '7', '8' ) NOT NULL DEFAULT '1',
`price` DECIMAL( 7, 2 ) UNSIGNED NOT NULL
) ENGINE = InnoDB;

CREATE TABLE `discount` (
`did` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`pid` SMALLINT( 5 ) UNSIGNED NOT NULL,
`sDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`eDate` DATETIME NOT NULL,
`dPrice` DECIMAL( 7, 2 ) UNSIGNED NOT NULL,
FOREIGN KEY ( `pid` ) REFERENCES `product`(`pid`)
    ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;

Я пытаюсь получить результат ровно по 1 строке для каждого продукта и NULL dPrice или dPrice, если есть запись со скидкой sDate < NOW() и eDate > NOW().

Я пробовал:

select p.pid, name, price, dPrice, qty
from product p left join discount d
on p.pid = d.pid
where d.sDate<now() and d.eDate>now();

Проблема с этим - это возврат только продуктов с действующей скидкой. Продукты без скидки или истекшие/будущие скидки не отображаются.

Далее я попытался:

select p.pid, name, price, dPrice, qty
from product p left join discount d
on p.pid = d.pid
where (d.sDate<now() and d.eDate>now()) or dPrice is null;

Это приблизилось к моему желаемому результату на 1 шаг, где он перечислял продукты с действующими скидками и продуктами без каких-либо скидок, но я все еще не хватает продуктов с установленными истекшими/будущими скидками.

Проверка того, что только 1 скидка активна в любое время, выполняется в PHP и не требуется включать в этот оператор. Любая помощь очень ценится!

  • 0
    какая база данных системы? какая версия ??
Теги:
select
join
left-join

4 ответа

4
Лучший ответ
select p.pid, name, price, dPrice, qty
from product p 

left join discount d on p.pid = d.pid and d.sDate<now() and d.eDate>now()

Более эффективный и более "стандартный", чем подзапрос.

  • 0
    Woo! Это тоже работает ...
  • 0
    Это так же, как принятый ответ, но я разместил это ранее;)
2

Что насчет

SELECT p.name, d.dPrice
FROM   product p LEFT JOIN discount d
ON     p.pid = d.pid AND now() BETWEEN d.sDate AND d.eDate
  • 0
    ЛОЛ!! 3 способа сделать работу, и я не могу придумать один! Спасибо чувак!
1

Вероятно, вы хотите, чтобы подзапрос возвращал отфильтрованную версию discount, после чего вы можете присоединиться к ней с помощью product.

select p.pid, name, price, dPrice, qty
from product p left join
(select * from discount where sDate<now() and eDate>now()) d
on p.pid = d.pid;

(Здесь может быть небольшая ошибка в синтаксисе SQL, но вы получаете идею: поскольку вы хотите, чтобы предложение WHERE применялось к одной таблице, вы применяете его к этой таблице в подзапросе, а затем присоединяетесь к набор данных результата, вместо того, чтобы сначала присоединяться к таблицам, а затем фильтровать.)

  • 0
    Нет, ошибок нет. =) Спасибо, мужик!
0

То, что Outer Joins было изобретено для.

select p.*,d.dPrice from product p left outer join discount d on p.pid=d.pid and now() between d.sDate and d.eDate

Вы можете использовать аббревиатуру left join вместо полного left outer join. Тем не менее, все же хорошо помнить, что они являются внешними соединениями, а не обычными внутренними соединениями.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню