我有两个表,Sales(ISBN,Sale_Time,[Sale Data Fields])和Affiliate_Sales(ISBN,Affiliate_Sale-Time,[Affiliate Data Fields])。
我想查询给定的一组ISBN的所有未到期销售(< 24小时)和未到期的Affiliate_Sales(< 72小时)。即使有未过期的销售但没有未到期的Affiliate_Sales,我也希望返回一行给定的ISBN,反之亦然(但是当它们都没有时应该返回任何内容)。我相信这被称为全加入。
我认为UNION不会在这里工作,因为除了ISBN之外,所有字段的表都不同。
这个问题的答案是在两个表中进行正确连接并检查到期的查询。
更新:正如您在下面的评论中所看到的,我正在尝试获取所有销售数据和所有Affiliate_Sales数据,而不仅仅是ISBN和时间。
更新2:结果如下所示
ISBN Sale_DateTime [Sale Fields…] Affiliate_Sale_DateTime [Affiliate Sale Fields…] 1 11/6/2010 11:28 All the sale Fields 11/6/2010 0:28 All the affiliate Sale fields 2 NULL NULLs 11/6/2010 0:28 All the affiliate Sale fields 3 11/6/2010 11:28 All the sale Fields NULL NULLs
如果得到这个需要在SQL端进行更多处理,而不仅仅是像Bruno的长查询所做的那样做两个基本的SELECT查询,也许我应该做两个?
答案 0 :(得分:0)
如果您使用“AS”来定义要返回的字段的名称以便它们匹配,UNION应该可以工作。例如:
SELECT ISBN, Sale_Time FROM Sales
UNION ALL
SELECT ISBN, Affiliate_Sale_Time AS Sale_Time FROM Affiliate_Sales
答案 1 :(得分:0)
如果您在Sales表中始终拥有ISBN,那么您可以完全加入并获得您正在寻找的结果。否则,你需要离开加入。
select *
from Sales s
FULL OUTER JOIN Affiliate_Sales asa on asa.ISBN = s.ISBN
where DATEDIFF(hh, s.Sale_Time, GETDATE()) < 24
OR DATEDIFF(hh, asa.Sale_Time, GETDATE()) < 72
编辑 - 尝试上述或以下内容:
SELECT ISBN, Sale_Time
FROM Sales s
where DATEDIFF(hh, s.Sale_Time, GETDATE()) < 24
UNION ALL
SELECT ISBN, Affiliate_Sale_Time AS Sale_Time
FROM Affiliate_Sales asa
where DATEDIFF(hh, asa.Sale_Time, GETDATE()) < 72
如果您想要更多字段,则必须具体命名它们,除非表格结构相同。 FULL JOIN将为您提供所有结果。我之前的回答包括INNER JOIN,这会限制你的结果。
编辑 - 选择不匹配字段的示例:
select itemid, null, path, null, name
from Catalog
union all
select itemid, dsid, null, username, null
from DataSource
答案 2 :(得分:0)
您确实遇到了FULL OUTER JOIN
问题,但遗憾的是,目前MySQL尚不支持此问题。
幸运的是,我们可以在表A和B之间模仿FULL OUTER JOIN
:
由于您的表格除了ISBN以外的所有字段都有所不同,我们需要分两步完成:
以下是检查查询的示例脚本:
CREATE TABLE sales ( isbn INT NOT NULL ,sale_time TIMESTAMP NOT NULL ,sale_value VARCHAR(100) ,PRIMARY KEY (isbn) ); CREATE TABLE affiliate_sales ( isbn INT NOT NULL ,sale_time TIMESTAMP NOT NULL ,affiliate_sale_value VARCHAR(100) ,PRIMARY KEY (isbn) ); INSERT INTO sales (isbn,sale_time,sale_value) VALUES (1,TIMESTAMPADD(HOUR,-30,NOW()),'expired_sale'); INSERT INTO sales (isbn,sale_time,sale_value) VALUES (2,TIMESTAMPADD(HOUR,-34,NOW()),'expired_sale'); INSERT INTO sales (isbn,sale_time,sale_value) VALUES (3,TIMESTAMPADD(HOUR,-23,NOW()),'unexpired_sale'); INSERT INTO sales (isbn,sale_time,sale_value) VALUES (4,TIMESTAMPADD(HOUR,-12,NOW()),'unexpired_sale'); INSERT INTO sales (isbn,sale_time,sale_value) VALUES (5,TIMESTAMPADD(HOUR,-12,NOW()),'unexpired_sale_only'); INSERT INTO affiliate_sales (isbn,sale_time,affiliate_sale_value) VALUES (1,TIMESTAMPADD(HOUR,-74,NOW()),'expired_affiliate_sale'); INSERT INTO affiliate_sales (isbn,sale_time,affiliate_sale_value) VALUES (2,TIMESTAMPADD(HOUR,-54,NOW()),'unexpired_affiliate_sale'); INSERT INTO affiliate_sales (isbn,sale_time,affiliate_sale_value) VALUES (3,TIMESTAMPADD(HOUR,-80,NOW()),'expired_affiliate_sale'); INSERT INTO affiliate_sales (isbn,sale_time,affiliate_sale_value) VALUES (4,TIMESTAMPADD(HOUR,-12,NOW()),'unexpired_affiliate_sale'); INSERT INTO affiliate_sales (isbn,sale_time,affiliate_sale_value) VALUES (6,TIMESTAMPADD(HOUR,-44,NOW()),'unexpired_affiliate_sale_only');
以下是提取所需数据的查询(抱歉格式错误,我无法找到如何在预阻塞内正确显示):
SELECT unexpired_sal.isbn
, sal.sale_time, sal.sale_value
, afs.sale_time affiliate_sale_time, afs.affiliate_sale_value
FROM (
SELECT sal.isbn
FROM (
SELECT isbn FROM sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 24
) sal
LEFT JOIN (
SELECT isbn FROM affiliate_sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 72
) afs
ON afs.isbn = sal.isbn
UNION ALL
SELECT afs.isbn
FROM (
SELECT isbn FROM sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 24
) sal
RIGHT JOIN (
SELECT isbn FROM affiliate_sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 72
) afs
ON afs.isbn = sal.isbn
WHERE sal.isbn IS NULL
) unexpired_sal
LEFT JOIN (
SELECT * FROM sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 24
) sal
ON sal.isbn = unexpired_sal.isbn
LEFT JOIN (
SELECT * FROM affiliate_sales
WHERE TIMESTAMPDIFF(HOUR,sale_time,NOW()) < 72
) afs
ON afs.isbn = unexpired_sal.isbn
;
您将获得以下输出:
+------+---------------------+---------------------+---------------------+-------------------------------+ | isbn | sale_time | sale_value | affiliate_sale_time | affiliate_sale_value | +------+---------------------+---------------------+---------------------+-------------------------------+ | 3 | 2010-11-06 11:28:08 | unexpired_sale | NULL | NULL | | 4 | 2010-11-06 22:28:08 | unexpired_sale | 2010-11-06 22:28:08 | unexpired_affiliate_sale | | 5 | 2010-11-06 22:28:08 | unexpired_sale_only | NULL | NULL | | 2 | NULL | NULL | 2010-11-05 04:28:08 | unexpired_affiliate_sale | | 6 | NULL | NULL | 2010-11-05 14:28:08 | unexpired_affiliate_sale_only | +------+---------------------+---------------------+---------------------+-------------------------------+ 5 rows in set (0.00 sec)
答案 3 :(得分:0)
定义要求
您在问题和评论中指定了一些矛盾和定义不足的要求,但我想这是您提出要求的原因之一。
让我为你列出
(我正在使用术语子集,因为在概念层面上指定未过期子集的条件并不重要)
以下是一些含义
如果要列出两个表中的ISBN +字段以查找仅在其中一个子集中的条目,则必须为另一方提供NULL;这与#3
两个表中的ISBN都是唯一的吗?如果是,则忽略这一点:如果ISBN不是唯一的,那么您需要指定如何连接两个表的子集,否则从每个表中获取每行的每一行
如果ISBN是唯一的
现在,如果您的ISBN在两个表中都是唯一的,那么Bruno的答案似乎指向了正确的方向(尽管它没有完全通过他的SQL,但它看起来确实有点过于复杂)。
在mysql中实现OUTER JOINS的方法是
如果此处使用的某些术语不明确,请参阅Common MySQL Queries上的示例。
如果ISBN不是唯一的
您需要定义如何加入,仅加入ISBN将返回子集的笛卡尔积(在其他任何情况下,其他字段肯定不是您所需要的。)
修改强> 澄清后,您可以尝试此解决方案
SELECT * FROM Sales a LEFT JOIN Affiliate_Sales b ON a.ISBN=b.ISBN
WHERE TIMESTAMPDIFF(HOUR, Sale_DateTime, Now()) < 24
AND (TIMESTAMPDIFF(HOUR, Affiliate_Sale_DateTime, Now()) < 72
OR Affiliate_Sale_DateTime IS NULL)
UNION ALL
SELECT * FROM Sales a RIGHT JOIN Affiliate_Sales b ON a.ISBN=b.ISBN
WHERE TIMESTAMPDIFF(HOUR, Affiliate_Sale_DateTime, Now()) < 72
AND Sale_DateTime IS NULL;
如果你想缩短它,你需要创建视图。另外,请看一下提供的链接,这是非常好的。