【问题标题】: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 1oracle 中不存在。
  • 我是 SQL Fiddle 的新手,在选择 Oracle 时无法构建架构。下次我会研究它。

标签: sql oracle greatest-n-per-group


【解决方案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 的非空外键,则不需要加入表(如上)。

【讨论】:

【解决方案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 中不起作用。
      猜你喜欢
      • 1970-01-01
      • 2020-01-25
      • 1970-01-01
      • 2011-03-07
      • 2017-10-08
      • 2014-11-06
      • 1970-01-01
      • 2011-05-26
      • 2019-10-04
      相关资源
      最近更新 更多