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

StackOverflow https://stackoverflow.com/questions/1884461

Вопрос

У меня есть 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 и не должна быть включена в это утверждение. Любая помощь высоко ценится!

Это было полезно?

Решение

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

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

Другие советы

Как насчет

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

Вы, наверное 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 Пункт.

Вот что именно Внешние соединения были изобретены для.

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. Анкет Тем не менее, все еще хорошо помнить, что они являются внешними соединениями, а не обычными внутренними соединениями.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top