在多个列上交叉连接,没有重复

时间:2014-08-01 17:43:58

标签: mysql cross-join

我们有两个表格,其中主要是唯一的电子邮件,以及发送交易(从一个系统发送)和接收(在另一个系统中)的日期:

CREATE TABLE `alpha` (
  `id` int(11) NOT NULL,
  `email` varchar(255) NOT NULL,
  `date_sent` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `alpha`
VALUES
(12344,'loremipsum@example.com','2013-01-01 02:26:04'),
(12345,'foobar@example.com','2013-01-01 04:39:16'),
(12346,'foobar@example.com','2013-01-01 04:43:18');

CREATE TABLE `bravo` (
  `id` int(11) NOT NULL,
  `email` varchar(60) DEFAULT NULL,
  `date_recvd` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `bravo`
VALUES
(98764,'loremipsum@example.com','2013-01-01 03:29:12'),
(98765,'foobar@example.com','2013-01-01 05:42:08'),
(98766,'foobar@example.com','2013-01-01 05:46:08');

通过简单的电子邮件联接和日期的m / d / y:

select a.id, a.date_sent, b.id, b.date_recvd
from alpha a inner join bravo b
  on a.email = b.email and date_format(a.date_sent,'%m/%d/%Y') = date_format(b.date_recvd,'%m/%d/%Y')

我们收到电子邮件+日期的每一个排列:

| a.id  | a.date_sent         | b.id  | b.date_recvd        |
+-------+---------------------+-------+---------------------+
| 12344 | 2013-01-01 02:26:04 | 98764 | 2013-01-01 03:29:12 |
| 12345 | 2013-01-01 04:39:16 | 98765 | 2013-01-01 05:42:08 |
| 12346 | 2013-01-01 04:43:18 | 98765 | 2013-01-01 05:42:08 |
| 12345 | 2013-01-01 04:39:16 | 98766 | 2013-01-01 05:46:08 |
| 12346 | 2013-01-01 04:43:18 | 98766 | 2013-01-01 05:46:08 |

我们想要的是更像这样的东西,我们首先加入电子邮件,然后只加入他们排序的订单中的日期:

| a.id  | a.date_sent         | b.id  | b.date_recvd        |
+-------+---------------------+-------+---------------------+
| 12344 | 2013-01-01 02:26:04 | 98764 | 2013-01-01 03:29:12 |
| 12345 | 2013-01-01 04:39:16 | 98765 | 2013-01-01 05:42:08 |
| 12346 | 2013-01-01 04:43:18 | 98766 | 2013-01-01 05:46:08 |

但我甚至不确定如何处理这个问题?

澄清:我们想做的是,电子邮件相同,消除重复,以便日期差距最小。

1 个答案:

答案 0 :(得分:1)

在某些情况下,以下查询将提供您想要的结果:

SELECT an.*, bn.*
FROM 
  (SELECT a.*,
    (CASE a.email
       WHEN @curEmail THEN @i:=@i+1
       ELSE                @i:=1 AND @curEmail:=a.email
    END) AS rn
  FROM (SELECT @i:=0, @curEmail:='') foo, (SELECT * FROM alpha ORDER BY email, date_sent) a) an
JOIN
  (SELECT b.*,
    (CASE b.email
       WHEN @curEmail THEN @i:=@i+1
       ELSE                @i:=1 AND @curEmail:=b.email
    END) AS rn
  FROM (SELECT @i:=0, @curEmail:='') foo, (SELECT * FROM bravo ORDER BY email, date_recvd) b) bn
ON an.email=bn.email AND an.rn=bn.rn;

使用您提供的有限数据,这是有效的。你可以在这里看到它:SQLFiddle

这是做什么的:

  • 将一个列添加到alpha ...这是使用相同电子邮件的所有行中的某种行编号,按date_sent排序
  • 将一个列添加到bravo ...与上面相同
  • 在电子邮件和
  • 上加入两个结果集

只有当alpha和bravo包含匹配良好的良好数据时,这才有效。

条件非常严格,特别是在bravo牌桌上。特别是, bravo不应包含与早期行 ...行匹配电子邮件与alpha,但date_recvd小于第一个alpha date_sent(使用相同的电子邮件)。

您可以详细说明这一点,并制定一个更复杂的版本,适用于您的问题中建议的电子邮件,日期(仅限日期)和rownumber。但我不认为这是一个很好的解决方案。我发现你在date_sent和date_recvd之间有很大的差距。如果间隙在午夜滚动,您将无法正确匹配行。