如何在加入时仅返回最新记录[重复]
Posted
技术标签:
【中文标题】如何在加入时仅返回最新记录[重复]【英文标题】:How to return only latest record on join [duplicate] 【发布时间】:2015-07-24 11:56:16 【问题描述】:我正在加入表格。我只想根据日期字段从联接表中返回一条记录。
这是我迄今为止所做的一个简化的小提琴:http://sqlfiddle.com/#!3/be0cdd/2
我的桌子:
CUSTOMER
| CustomerID |
--------------
| 1 |
PURCHASE
| PurchaseID | CustomerID | ProductID | CreateDate | ArchiveFlag |
------------------------------------------------------------------
| 1 | 1 | 443 | 01-FEB-15 | F |
| 2 | 1 | 551 | 01-MAR-15 | F |
| 3 | 1 | 151 | 01-JAN-15 | F |
| 4 | 1 | 654 | 01-MAY-15 | T |
| 5 | 1 | 345 | 01-APR-15 | T |
这是查询本身:
select *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F';
我只想为每位客户退回未归档的最新购买(在本例中为购买 ID 2)。
理想输出:
| CustomerID | PurchaseID | CustomerID_2 | ProductID | CreateDate | ArchiveFlag |
|--------------------------------------------------------------------------------
| 1 | 2 | 1 | 551 | 01-MAR-15 | F |
【问题讨论】:
请使用示例数据和所需结果编辑您的问题。 还要注意你的标签是oracle
,但你的SQL Fiddle是SQL Server
。区别在于TOP 1
在oracle
中不存在。
我是 SQL Fiddle 的新手,在选择 Oracle 时无法构建架构。下次我会研究它。
【参考方案1】:
Oracle 12c 引入了行限制子句,您可以这样做(如果您只想要一个结果):
SELECT *
FROM customer c
INNER JOIN purchase p
ON ( c.customerid = p.customerid )
WHERE p.archiveflag = 'F'
ORDER BY
CreateDate DESC
FETCH FIRST 1 ROW ONLY
在早期版本中,您可以这样做:
SQL Fiddle
Oracle 11g R2 架构设置:
create table CUSTOMER(CustomerID INT);
create table PURCHASE(PurchaseID INT, CustomerID INT, ProductID INT, CreateDate date, ArchiveFlag char);
insert into CUSTOMER values(1);
insert into CUSTOMER values(2);
insert into PURCHASE values(1,1,443,'01-FEB-15','F');
insert into PURCHASE values(2,1,551,'01-MAR-15','F');
insert into PURCHASE values(3,1,151,'01-JAN-15','F');
insert into PURCHASE values(4,1,654,'01-MAY-15','T');
insert into PURCHASE values(5,1,345,'01-APR-15','T');
insert into PURCHASE values(6,2,234,'01-MAY-15','T');
insert into PURCHASE values(7,2,134,'01-APR-15','F');
insert into PURCHASE values(8,2,999,'01-JAN-15','F');
insert into PURCHASE values(9,2,724,'07-JUN-15','F');
insert into PURCHASE values(10,2,345,'01-JUN-15','T');
查询 1 - 如果您只想获取单个客户的最新信息:
SELECT *
FROM (
SELECT *
FROM Purchase
WHERE archiveflag = 'F'
AND CustomerID = 1
ORDER BY
CreateDate DESC
)
WHERE ROWNUM = 1
Results:
| PURCHASEID | CUSTOMERID | PRODUCTID | CREATEDATE | ARCHIVEFLAG |
|------------|------------|-----------|-------------------------|-------------|
| 2 | 1 | 551 | March, 01 2015 00:00:00 | F |
查询 2 - 如果您想为所有客户获取最新信息:
SELECT PurchaseID,
CustomerID,
ProductID,
CreateDate,
ArchiveFlag
FROM (
SELECT p.*,
ROW_NUMBER() OVER ( PARTITION BY p.CustomerID ORDER BY CreateDate DESC ) RN
FROM purchase p
WHERE ArchiveFlag = 'F'
)
WHERE RN = 1
Results:
| PURCHASEID | CUSTOMERID | PRODUCTID | CREATEDATE | ARCHIVEFLAG |
|------------|------------|-----------|-------------------------|-------------|
| 2 | 1 | 551 | March, 01 2015 00:00:00 | F |
| 9 | 2 | 724 | June, 07 2015 00:00:00 | F |
如果PURCHASE.CUSTOMERID
是链接到CUSTOMER.CUSTOMERID
的非空外键,则不需要加入表(如上)。
【讨论】:
谢谢,但如果我想为每个客户退回最新购买的商品,我该怎么办? sqlfiddle.com/#!4/1fb7b/1【参考方案2】:我想你想用row_number()
:
select *
from customer c join
(select p.*,
row_number() over (partition by p.customerid order by p.createdate desc) as seqnum
from purchase p
where p.archiveflag = 'F'
) p
on c.customerid = p.customerid and seqnum = 1;
【讨论】:
【参考方案3】:SQL Fiddle
架构设置
create table CUSTOMER(CustomerID int)
create table PURCHASE(PurchaseID int, CustomerID int, ProductID int, CreateDate date, ArchiveFlag char)
insert into CUSTOMER values(1)
insert into CUSTOMER values(2)
insert into PURCHASE values(1,1,443,'01-FEB-15','F')
insert into PURCHASE values(2,1,551,'01-MAR-15','F')
insert into PURCHASE values(3,1,151,'01-JAN-15','F')
insert into PURCHASE values(4,1,654,'01-MAY-15','T')
insert into PURCHASE values(5,1,345,'01-APR-15','T')
insert into PURCHASE values(6,2,331,'01-FEB-15','T')
insert into PURCHASE values(7,2,298,'01-JUN-15','F')
查询以获取所有客户的最新待处理
select *
from purchase pa join customer c on c.customerid=pa.customerid
where pa.archiveflag = 'F'
and pa.createdate=(select max(createdate)
from purchase pb
where pa.customerid=pb.customerid
and pb.archiveflag='F')
输出
| PurchaseID | CustomerID | ProductID | CreateDate | ArchiveFlag | CustomerID |
|------------|------------|-----------|------------|-------------|------------|
| 2 | 1 | 551 | 2015-03-01 | F | 1 |
| 7 | 2 | 298 | 2015-06-01 | F | 2 |
【讨论】:
【参考方案4】:您可以像这样在查询中使用 top 和 order by
select Top 1 *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F'
Order by p.CreateDate Desc;
【讨论】:
TOP
在 Oracle 中无效【参考方案5】:
只需使用 where 子句:告诉你想要购买 ID 2:如下所示:
选择 * 从 选择 * 来自客户 c 加入采购p 在 c.customerid = p.customerid 和 p.archiveflag = 'F'; 按 CreateDate 顺序排序 其中 PurchasedID = 2;
【讨论】:
drc15 说他想要的是最新日期而不是那个特定的 ID。【参考方案6】:试试这个..
select top 1 *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F'
order by CreateDate desc;
【讨论】:
这在 Oracle 中不起作用。以上是关于如何在加入时仅返回最新记录[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Django queryset - 在对象上应用过滤器时仅返回匹配的多记录