问题
I'm joining tables. I only want to return one record from the joining table, based on a date field.
Here's a simplified fiddle of what I've done so far: http://sqlfiddle.com/#!3/be0cdd/2
My tables:
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 |
and here's the query itself:
select *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F';
I only want to return the latest purchase that isn't archived (in this example, purchase ID 2) for each customer.
Ideal output:
| CustomerID | PurchaseID | CustomerID_2 | ProductID | CreateDate | ArchiveFlag |
|--------------------------------------------------------------------------------
| 1 | 2 | 1 | 551 | 01-MAR-15 | F |
回答1:
Oracle 12c introduced a row limiting clause and you could do (if you only want a single result):
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
In earlier versions you can do:
SQL Fiddle
Oracle 11g R2 Schema Setup:
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');
Query 1 - If you only want to get the latest for a single customer:
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 |
Query 2 - If you want to get the latest for all customers:
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 |
If PURCHASE.CUSTOMERID
is a not null foreign key linked to CUSTOMER.CUSTOMERID
then you do not need to join the tables (as above).
回答2:
I think you want to use 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
Schema setup
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')
Query to get latest pending for all customers
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')
Output
| PurchaseID | CustomerID | ProductID | CreateDate | ArchiveFlag | CustomerID |
|------------|------------|-----------|------------|-------------|------------|
| 2 | 1 | 551 | 2015-03-01 | F | 1 |
| 7 | 2 | 298 | 2015-06-01 | F | 2 |
回答4:
You can use top and order by in your query like this
select Top 1 *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F'
Order by p.CreateDate Desc;
回答5:
Just use where clause: as told you wanted purchase ID 2: do as below:
SELECT * FROM select * from customer c join purchase p on c.customerid = p.customerid and p.archiveflag = 'F'; order by CreateDate desc where PurchasedID = 2;
回答6:
Try this one..
select top 1 *
from customer c
join purchase p
on c.customerid = p.customerid
and p.archiveflag = 'F'
order by CreateDate desc;
来源:https://stackoverflow.com/questions/31609961/how-to-return-only-latest-record-on-join