使用Actian PSQL v13:
我正在尝试联接两个表并按几个条件过滤结果集。一个表是客户销售历史记录。另一个表将客户关联到购买组。并非所有客户都在购买组中,因此我正在执行左联接以获得所有可能的销售历史记录结果。我不希望结果包括购买组"SALREP"中的任何人,但我确实希望看到不属于任何购买组的客户。此外,所谓的部分"FREIGHT"正在从结果中过滤掉。
我遇到的问题是,当我过滤掉"SALREP"组时,只选择购买组中的客户; 所有不在购买组中的客户都丢失了。
我已经通过注释掉"SALREP"的过滤器对此进行了测试,结果集确实包括不在购买组中的客户。我还尝试使用不同的过滤器方法,以防Actian PSQL挑剔。例如,我尝试了不同的"不等于"方法,例如!=
,not()
和<>
;问题仍然存在。另外,我使用left join
和left outer join
有同样的问题。
下面是查询:
select T2.GROUP_CUST, T1.DATE_INVOICE, T1.SALESPERSON, T1.CUSTOMER, T1.PRODUCT_LINE, T1.PART, T1.DESCRIPTION, T1.QTY_SHIPPED, T1.EXTENSION
from ORDER_HIST_LINE T1
left join BUYING_GROUP T2 on T1.CUSTOMER=T2.CUSTOMER
where DATE_INVOICE > '2019-06-13' and PART != 'FREIGHT'
and T2.GROUP_CUST != 'SALREP'
and T1.CUSTOMER in ('ABC', 'DEF', 'GHI')
order by T1.CUSTOMER;
预期结果集应包括 2019-06-13 之后开具发票的任何内容,不包括名为"FREIGHT"的部分,并且客户不在名为"SALREP"的组中。 但是,实际的结果集不完整。例如:
CUSTOMER | GROUP_CUST | DATE_INVOICE | PART | etc.
-----------------------------------------------------
ABC | A12 | 2019-06-14 | WIDGET
DEF | A12 | 2019-06-14 | GEAR
基本上,所有不属于任何购买组的客户都被排除在外。
注释掉and T2.GROUP_CUST != 'SALREP'
的部分,并找到预期结果。例如:
CUSTOMER | GROUP_CUST | DATE_INVOICE | PART | etc.
-----------------------------------------------------
ABC | A12 | 2019-06-14 | WIDGET
DEF | A12 | 2019-06-14 | GEAR
GHI | | 2019-06-15 | WIDGET
我正在考虑创建选择查询的左联接,该查询首先从购买组中删除"SALREP",但这不允许结果集识别和删除该组中的任何人。 例如:left join (select * from BUYING_GROUP where GROUP_CUST != 'SALREP') T2
8/7/19 进一步尝试: 我在MySQL v5.0.12上发现了同样的困境。我可以离开联接表以产生不匹配的结果。我可以在那些不匹配的结果上过滤左侧表,而不会意外丢失任何内容。但是,我无法在不消失所有不匹配行的情况下在这些不匹配的结果上筛选正确的表。
您需要在ON
子句中的第二个表上放置条件。 唯一明显的引用是T2.GROUP_CUST
,但它也可能适用于DATE_INVOICE
和PART
:
from ORDER_HIST_LINE T1 left join
BUYING_GROUP T2
on T1.CUSTOMER = T2.CUSTOMER and
T2.GROUP_CUST <> 'SALREP'
where DATE_INVOICE > '2019-06-13' and
PART <> 'FREIGHT' and
T1.CUSTOMER in ('ABC', 'DEF', 'GHI')
order by T1.CUSTOMER;
谢谢 https://mode.com/resources/sql-tutorial/sql-joins-where-vs-on/。文章提到,"WHERE 子句中的过滤也可以过滤空值,所以我们添加了一个额外的行来确保包含空值。
这促使我进行测试并意识到,在针对正确的表进行筛选时,必须明确声明要包含该筛选列的 NULL 值(不匹配的行),否则这些不匹配的行将从结果集中删除。我还发现有必要将过滤器对放在括号中,否则结果集会"爆炸"。我测试并发现只有在针对正确的表进行过滤时才有必要这样做;针对左侧表进行过滤(显然)没有此问题。
最终答案:
select T2.GROUP_CUST, T1.DATE_INVOICE, T1.SALESPERSON, T1.CUSTOMER, T1.PRODUCT_LINE,
T1.PART, T1.DESCRIPTION, T1.QTY_SHIPPED, T1.EXTENSION
from ORDER_HIST_LINE T1
left join BUYING_GROUP T2 on T1.CUSTOMER=T2.CUSTOMER
where DATE_INVOICE > '2019-06-13' and PART != 'FREIGHT'
and (T2.GROUP_CUST != 'SALREP' or T2.GROUP_CUST is null)
and T1.CUSTOMER in ('ABC', 'DEF', 'GHI')
order by T1.CUSTOMER;
请注意行and (T2.GROUP_CUST != 'SALREP' or T2.GROUP_CUST is null)
。