我无法找到解决此问题的最佳方法:
我有2个表,test_a和test_b。
Test_a存储客户购买产品的详细信息。
Test_b基本上是一个产品表,其中列出了我要跟踪的产品。客户可能会购买许多产品,但并非所有产品都在test_b中,只有我要跟踪的产品都在test_b中。
我想跟踪每个客户不购买哪些产品。
test_a和test_b的简化表如下所示:
test_a
Test_b
我已经尝试过以下语句:
select * from test_a a
right outer join test_b b
on trim(a.product) = trim(b.product)
上面的声明仅告诉我根本没有客户购买哪种产品,而没有告诉我每个特定客户没有购买哪种产品。我希望结果显示对于不购买该产品的特定客户,该产品的购买日期为空白,如果他们购买了该产品,则购买日期字段为实际购买日期。
***更新
我希望看到的结果是:
是否有一种干净有效的方法来实现上述目标?我能想到的一种方法可能是执行完整的外部联接,然后过滤掉不在test_b中的乘积,但这似乎不是很有效。我真正的test_a表有几百万条记录,而test_b包含近千条记录。
附件是我上面提到的示例表的脚本:
CREATE TABLE "TEST_A"
( "ID" NUMBER(3,0),
"CUSTOMER" VARCHAR2(26 BYTE),
"PRODUCT" VARCHAR2(26 BYTE),
"DATEOFPURCHASE" DATE
) ;
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (1,'A ','P1',to_date('12-DEC-19','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (2,'A ','P2',to_date('01-NOV-17','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (3,'A ','P3',to_date('01-JAN-20','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (4,'A ','P4',to_date('15-JUL-15','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (5,'B','P1',to_date('01-APR-16','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (6,'B','P3',to_date('12-AUG-18','DD-MON-RR'));
Insert into TEST_A (ID,CUSTOMER,PRODUCT,DATEOFPURCHASE) values (7,'C','P3',to_date('15-JUN-12','DD-MON-RR'));
CREATE TABLE "TEST_B"
( "PRODUCT" VARCHAR2(26 BYTE),
"DEPARTMENT" NUMBER(3,0)
) ;
Insert into TEST_B (PRODUCT,DEPARTMENT) values ('P1',1);
Insert into TEST_B (PRODUCT,DEPARTMENT) values ('P2',2);
答案 0 :(得分:1)
这返回期望的结果,但是...我不太喜欢它。
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select distinct y.customer, b.product, x.dateofpurchase
2 from test_b b cross join (select a.customer
3 from test_a a
4 where a.product in (select b.product from test_b b)
5 ) y
6 left join test_a x on x.customer = y.customer and x.product = b.product
7 order by y.customer, b.product;
CUSTOMER PRODUCT DATEOFPURC
-------------------------- -------------------------- ----------
A P1 12.12.2019
A P2 01.11.2017
B P1 01.04.2016
B P2
SQL>
答案 1 :(得分:0)
我建议left join
胜过right join
,但是您需要一个where
子句来查找不匹配项:
select b.* -- why bring in columns from a when you know they are all NULL?
from test_b b left join
test_a a
on a.product = b.product
where a.product is null;
我删除了trim()
。仅当您的数据很脏并且没有正确声明外键关系时,您才需要这样做。
我个人比较喜欢not exists
:
select b.*
from test_b b
where not exists (select 1 from test_a a where a.product = b.product);
编辑:
如果您希望每个客户 ,那么对客户和产品进行cross join
来获取两者的所有组合。然后删除存在的内容:
select c.customer, b.product
from (select distinct customer from test_a) c cross join
test_b b left join
test_a a
on a.customer = c.customer and a.product = b.product
where a.customer is null; -- no match
答案 2 :(得分:0)
此PIVOT可用于查看哪些客户购买了哪些产品
select *
from (
select customer, product
from test_a )
pivot
( count(*)
for product in ('P1', 'P2', 'P3')
);