0

我有下表:

CREATE TABLE `relations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `relationcode` varchar(25) DEFAULT NULL,
  `email_address` varchar(100) DEFAULT NULL,
  `firstname` varchar(100) DEFAULT NULL,
  `latname` varchar(100) DEFAULT NULL,
  `last_contact_date` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

在这个表中有重复,这些是具有完全相同的关系代码和电子邮件地址的关系。他们可以在那里两次甚至十次。我需要一个查询来选择所有记录的 id,但不包括其中不止一次的那些。在这些记录中,我只想选择具有最新 last_contact_id 的记录。

我比 Mysql 更喜欢 Oracle,在 Oracle 中我可以这样做:

select * from (
    select row_number () over (partition by relationcode order by to_date(last_contact_date,'dd-mm-yyyy')) rank, 
           id, 
           relationcode,  
           email_address , 
           last_contact_date
    from RELATIONS)
where rank = 1

但我不知道如何修改此查询以在 MySql 中工作。我什至不敢在 MySQl 的单个查询中做同样的事情。有任何想法吗?

4

2 回答 2

3

执行此操作的正常方法是子查询以获取最新记录,然后将其与表连接:-

SELECT id, relationcode, email_address, firstname, latname, last_contact_date
FROM RELATIONS
INNER JOIN
(
    SELECT relationcode, email_address, MAX(last_contact_date) AS latest_contact_date
    FROM RELATIONS
    GROUP BY relationcode, email_address
) Sub1
ON RELATIONS.relationcode = Sub1.relationcode
AND RELATIONS.email_address = Sub1.email_address
AND RELATIONS.last_contact_date = Sub1.latest_contact_date

可以使用变量手动生成 Oracle 查询使用的等级。不过有点乱!

SELECT id, relationcode, email_address, firstname, latname, last_contact_date
FROM
(
    SELECT id, relationcode, email_address, firstname, latname, last_contact_date, @seq:=IF(@relationcode = relationcode AND @email_address = email_address, @seq + 1, 1) AS seq, @relationcode := relationcode, @email_address := email_address
    (
        SELECT id, relationcode, email_address, firstname, latname, last_contact_date
        FROM RELATIONS
        CROSS JOIN (SELECT @seq:=0, @relationcode := '', @email_address :='') Sub1
        ORDER BY relationcode, email_address, last_contact_date DESC
    ) Sub2
) Sub3
WHERE seq = 1

这使用子查询来初始化变量。如果关系代码和电子邮件地址与前一行相同,则添加序列号,否则将它们重置为 1 并存储在字段中。然后外部选择检查序列号(作为一个字段,而不是作为变量名),如果它是 1,则只返回记录。

请注意,我已将其作为多个子查询完成。部分是为了让你更清楚,但也是为了尝试强制 MySQL 执行它的顺序。MySQL如何表示它可能会命令执行可能导致问题的事情有几个可能的问题。他们从来没有为我做过,但我希望通过子查询强制执行命令。

于 2014-05-30T09:46:42.573 回答
1

这是一种适用于 MySQL 和 Oracle 的方法。relations它将问题改写为:从关系代码没有更大的地方获取所有行last_contact_date

它的工作原理是这样的:

select r.*
from relations r
where not exists (select 1
                  from relations r2
                  where r2.relationcode = r.relationcode and
                        r2.last_contact_date > r.last_contact_date
                 );

使用适当的索引,这在两个数据库中都应该非常有效。

注意:这假设last_contact_date存储为日期而不是字符串(如您的表格示例中所示)。将日期存储为字符串是一个非常糟糕的主意,您应该修复您的数据结构

于 2014-05-30T10:47:56.120 回答