从非规范化表中选择最新记录

时间:2011-11-01 15:51:32

标签: sql oracle select

我设置了一个包含列的表:

  • FNAME
  • L-NAME
  • 地址
  • 城市
  • 状态
  • 拉链
  • 客户ID
  • DATE_MODIFIED

数据基本上是非规范化的,所以看起来像

Ben -- Smith--***123first*** st -- NY -- NY -- 12101 -- 123 --  1-1-2011
Ben -- Smith--***123 1st st*** -- NY -- NY -- 12101 -- 123 -- 1-1-2011
Sara -- Smith -- BLAH BLAH BLAh

我正在尝试将这些记录复制到新表中,但我只想要每个客户ID一条记录。

我尝试过像

这样的事情
 insert into new_table(fname,lname,address,city,state,zip,Customer_ID,
                      date_modified)

 select fname,lname,address,city,state,zip,Customer_ID,date_modified
 group by (fname,lname,address,city,state,zip,Customer_ID,date_modified)

问题是有太多的地址和其他列具有相同的含义但文本不同(第一对第一)。所以该组将这两个记录留在新表中。如何通过选择max(修改日期)来获得每个客户ID的一条记录。基本上我只想通过customer_id而不是其他列进行分组,但在oracle中是不允许的。

2 个答案:

答案 0 :(得分:0)

以下是获得您想要的内容的几种方法之一。请记住,这样做规范化您的数据库。您仍然拥有customer_id,其中包含名字和姓氏以及地址。我可能会把它变成几个插入,一个用于获取所有唯一的客户ID以及Customers表的最新名称信息,然后是另一个地址插入。如果您需要有关更改的历史信息,则需要进行适当调整。

此外,如果您有两行具有相同的客户ID 相同完全 date_modified,则以下代码将无法正常运行。如果你遇到这种情况,你需要提出适当的业务逻辑来处理它。

INSERT INTO New_Table (
    fname,
    lname,
    address,
    city,
    state,
    zip,
    Customer_ID,
    date_modified )
SELECT
    OT1.fname,
    OT1.lname,
    OT1.address,
    OT1.city,
    OT1.state,
    OT1.zip,
    OT1.customer_id,
    OT1.date_modified
FROM
    (
    SELECT
        customer_id,
        MAX(date_modified) AS latest_date_modified
    FROM
        Old_Table
    GROUP BY customer_id) SQ
INNER JOIN Old_Table OT1 ON
    OT1.customer_id = OT1.customer_id AND
    OT1.date_modified = SQ.latest_date_modified

答案 1 :(得分:0)

通过使用分析(aka窗口)函数为每个客户选择第一行,这非常简单。如果两行具有相同的date_modified,则不定义采用哪一行。

INSERT INTO new_table (fname,lname,address,city,state,zip,Customer_ID,date_modified)
SELECT fname,
       lname,
       address,
       city,
       state,
       zip,
       Customer_ID,
       date_modified
FROM (
   SELECT fname,
          lname,
          address,
          city,
          state,
          zip,
          Customer_ID,
          date_modified,
          row_number() over (partition by customer_id order by date_modified desc) as rn
) 
WHERE rn = 1