简体   繁体   English

SQL Server:从联接查询中仅选择每个客户的最后一条记录

[英]SQL Server : select only last record per customer from a join query

Assume I have these 3 tables : 假设我有这三个表:

客户类型1

客户类型2

在此处输入图片说明

The first 2 tables define customers of different types ,ie second table has other columns which are not included in table 1 i just left them the same to save complexity. 前两个表定义了不同类型的客户,即第二个表具有表1中未包括的其他列,为节省复杂性,我将它们保留不变。

The third table defines orders for both types of customers . 第三张表定义了两种类型的客户的订单。 Each customer has more than one orders 每个客户有一个以上的订单

I want to select the last order for every customer, ie the order with order_id 4 for customer 1 which was created on 23/12/2016 and the order with order_id 5 for customer 2 which was created on 26/12/2016 我想为每个客户选择最后一个订单,即为2016年12月23日创建的customer 1的order_id 4的订单和为2016年12月26日创建的customer 2的订单为order_id 5的订单

I tried something like this : 我尝试过这样的事情:

select * 
from customertype1 
left join order on order.customer_id = customertype1.customer_id 
order by order_id desc;

But this gives me multiple records for every customer, as I have stated above I want only the last order for every customertype1 . 但这给了我每个客户多个记录,如上所述,我只希望每个customertype1的最后一个订单。

If you want the last order for each customer, then you only need the orders table: 如果要为每个客户最后一个订单,则只需要orders表:

select o.*
from (select o.*,
             row_number() over (partition by customer_id order by datecreated desc) as seqnum
      from orders o
     ) o
where seqnum = 1;

If you want to include all customers, then you need to combine the two tables. 如果要包括所有客户,则需要合并两个表。 Assuming they are mutually exclusive: 假设它们是互斥的:

with c as (
      select customer_id from customers1 union all
      select customer_id from customers2
     )
select o.*
from c left join
     (select o.*,
             row_number() over (partition by customer_id order by datecreated desc) as seqnum
      from orders o
     ) o
     on c.customer_id = o.customer_id and seqnum = 1;

A note about your data structure: You should have one table for all customers. 关于数据结构的注释:您应该为所有客户提供一张表。 You can then define a foreign key constraint between orders and customers . 然后,您可以在orderscustomers之间定义外键约束。 For the additional columns, you can have additional tables for the different types of customers. 对于其他列,您可以具有针对不同类型客户的其他表。

Use ROW_NUMBER() and PARTITION BY . 使用ROW_NUMBER()PARTITION BY

  • ROW_NUMBER() : it will give sequence no to your each row ROW_NUMBER() :它将为每行赋予序号
  • PARTITION BY : it will group your data by given column PARTITION BY :它将按给定的列对数据进行分组

When you use ROW_NUMBER() and PARTITION BY both together then first partition by group your records and then row_number give then sequence no by each group, so for each group you have start sequence from 1 当您同时使用ROW_NUMBER()PARTITION BY时,则首先按记录分组,然后row_number给出,然后按每个组的顺序进行排序,因此对于每个组,您都从1开始

Help Link: Example of ROW_NUMBER() and PARTITION BY 帮助链接: ROW_NUMBER()和PARTITION BY的示例

This is the general idea. 这是一般的想法。 You can work out the details. 您可以计算出细节。

with customers as
(select customer_id, customer_name
from table1
union
select customer_id, customer_name
from table2)

, lastOrder as
(select customer_id, max(order_id) maxOrderId
 from orders
 group by customer_id)

select *
from lastOrder join customers on lastOrder.Customer_id = customers.customer_id
 join orders on order_id = maxOrderId

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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