SQL Server:基于记录相关值的表联接
我正在尝试执行一种一般类型的查询,我不确定如何用文字表达它,以便找到最佳实践和执行示例的讨论 下面是一个示例用例 我有一个SQL Server:基于记录相关值的表联接,sql,sql-server,tsql,join,inner-join,Sql,Sql Server,Tsql,Join,Inner Join,我正在尝试执行一种一般类型的查询,我不确定如何用文字表达它,以便找到最佳实践和执行示例的讨论 下面是一个示例用例 我有一个客户表,其中包含客户信息和一个订单表。我想根据客户特征从订单中提取一部分记录,这些记录受客户表中作为数据包含的“最早”和“最晚”日期的限制。对于解决方案来说,我必须将查询结果限制在此日期范围内,这一范围因客户而异 客户 +------------+------------+----------+---------------------+-------------------
客户
表,其中包含客户信息和一个订单
表。我想根据客户特征从订单
中提取一部分记录,这些记录受客户
表中作为数据包含的“最早”和“最晚”日期的限制。对于解决方案来说,我必须将查询结果限制在此日期范围内,这一范围因客户而异
客户
+------------+------------+----------+---------------------+-------------------+
| CustomerID | Location | Industry | EarliestActiveOrder | LatestActiveOrder |
+------------+------------+----------+---------------------+-------------------+
| 001 | New York | Finance | 2017-11-03 | 2019-07-30 |
| 002 | California | Tech | 2018-06-18 | 2019-09-22 |
| 003 | New York | Finance | 2015-09-30 | 2019-02-26 |
| 004 | California | Finance | 2019-02-02 | 2019-08-15 |
| 005 | New York | Finance | 2017-10-19 | 2018-12-20 |
+------------+------------+----------+---------------------+-------------------+
+----------+------------+------------+---------+
| OrderID | CustomerID | StartDate | Details |
+----------+------------+------------+---------+
| 5430 | 003 | 2015-06-30 | ... |
| 5431 | 003 | 2016-03-31 | ... |
| 5432 | 003 | 2018-09-30 | ... |
| 5434 | 001 | 2018-11-05 | ... |
| 5435 | 001 | 2019-10-11 | ... |
订单
+------------+------------+----------+---------------------+-------------------+
| CustomerID | Location | Industry | EarliestActiveOrder | LatestActiveOrder |
+------------+------------+----------+---------------------+-------------------+
| 001 | New York | Finance | 2017-11-03 | 2019-07-30 |
| 002 | California | Tech | 2018-06-18 | 2019-09-22 |
| 003 | New York | Finance | 2015-09-30 | 2019-02-26 |
| 004 | California | Finance | 2019-02-02 | 2019-08-15 |
| 005 | New York | Finance | 2017-10-19 | 2018-12-20 |
+------------+------------+----------+---------------------+-------------------+
+----------+------------+------------+---------+
| OrderID | CustomerID | StartDate | Details |
+----------+------------+------------+---------+
| 5430 | 003 | 2015-06-30 | ... |
| 5431 | 003 | 2016-03-31 | ... |
| 5432 | 003 | 2018-09-30 | ... |
| 5434 | 001 | 2018-11-05 | ... |
| 5435 | 001 | 2019-10-11 | ... |
用文字表达的示例用例是:“给我纽约金融客户的所有有效订单”
理想的结果是从orders
表返回OrderID
的543154325434
的完整记录
考虑到一个包含10^6条记录的
orders
表,构造此类查询的一般好方法是什么
select o.*
from orders o
inner join customers c
on c.Customer_id = o.Customer_id
and o.StartDate between c.EarliestActiveOrder and c.LatestActiveOrder
and c.Industry = 'Finance'
and c.Location = 'New York'
此查询中的性能,请考虑以下索引:
orders(customer_id, StartDate)
customers(Customer_id, Industry, Location, EarliestActiveOrder, LatestActiveOrder)
假设结果集是订单的一小部分(比如少于1%的订单,但1%用于说明),我会这样表述查询:
select o.*
from customers c join
orders o
on o.Customer_id = c.Customer_id and
o.StartDate between c.EarliestActiveOrder and c.LatestActiveOrder
where c.Location = 'New York' and c.industry = 'Finance';
索引策略很棘手。对于较小的结果集,您可能希望首先限制客户,然后查找匹配的订单。此方法建议在以下方面建立索引:
客户(地点、行业、客户id、早期战术订单、后期战术订单)
订单(客户id,起始日期)
行业
-仅过滤:
客户(行业、客户id、早期战术订单、后期战术订单)
订单
表可能会更有效率。您可以尝试依赖优化器。或者只需将查询措辞为:
select o.*
from orders o
where exists (select 1
from customers c
where o.Customer_id = c.Customer_id and
o.StartDate between c.EarliestActiveOrder and c.LatestActiveOrder and
c.Location = 'New York' and c.industry = 'Finance'
);
在这种情况下,您需要一个关于客户(客户id)
的索引,但这可能已经是主键了,所以您可以。这样做的好处是,您不需要担心确切的筛选条件。缺点是对订单
进行全表扫描(但不包括加入
、分组依据
、或订单依据
)