繁体   English   中英

SQL连接显示左表,即使右表与哪里不匹配

[英]SQL join that displays left table even if right table doesn't match where

我有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;

我正在尝试为每个产品获得恰好一行的结果,如果有sDate < NOW()eDate > NOW()的折扣条目, sDate < NOW() dPrice或dPrice为NULL

我试过了:

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;

这比我期望的结果靠近了第一步,该结果列出了具有有效折扣的产品和无折扣的产品,但是我仍然缺少定义了过期/将来折扣的产品。

在PHP中可以随时检查只有1个折扣处于活动状态,并且不需要包含在此语句中。 任何帮助深表感谢!

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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM