1

我已经为此困惑了一段时间,并意识到是时候寻求帮助了。作为与第三方系统集成的一部分,我在现有系统中引入了一个附加表来管理记录的同步。我将缩小表结构以仅包含足够的细节来呈现问题:

Table 1: data
Columns: (int)data_id*, (varchar)name, (datetime)date_created

Table 2: sync
Columns: (int)sync_id*, (int)data_id, (int)result, (varchar)details,
         (datetime)date_created

* denotes primary index

当第三方系统尝试同步记录时,它使用 HTTP GET 请求,服务器端脚本返回一个 XML 响应,其中包含第一次等待同步的记录信息(此 data_id 将不存在同步记录) , 并且还记录等待重试的同步重试在先前尝试中失败的信息(此 data_id 的最新同步记录的结果值为 0)。然后,第三方系统使用 HTTP POST 请求到不同的服务器端脚本,该脚本提供有关它能够匹配和成功同步result = 1的记录 () 以及它不能匹配和同步的记录() 的反馈result = 0, details = "Error Message"

每个数据记录经常会有多个同步记录,因为有许多有效的场景可能会阻止在没有用户首先采取某些操作的情况下成功同步。

记录每次同步尝试很重要,因此仅向数据表添加同步列是不可接受的。

我试图使用 SQL 的伪代码版本是这样的:

  1. 从数据表和每条记录旁边获取所有记录。
  2. 对于这些记录中的每一个,通过匹配 data_id 来找到最新的同步记录,按降序排列同步记录(最新的在顶部),并将同步记录限制为 1(我们只需要最近的同步记录进行此查询)。
  3. 显示数据和最新同步记录中的列。如果不存在同步记录,则仍应显示数据记录,并且同步列只需填充 NULL 值。

到目前为止,我最接近的工作 SQL 语句使用LEFT JOIN

SELECT d.data_id, d.name, d.date_created, s.sync_id, s.result, s.details
FROM (
    SELECT data_id, name, date_created
    FROM data
) AS d 
LEFT JOIN (
    SELECT sync_id, data_id, result, details, date_created
    FROM sync 
    GROUP BY data_id
) AS s 
ON d.data_id = s.data_id 
ORDER BY d.date_created DESC;

不幸的是,这似乎没有获取最新的同步记录,但GROUP BY data_id似乎只是获取了它找到的第一个同步记录。MySQL 语法不允许我在行ORDER BY date_created DESC前放置一个GROUP BY data_id。如果我将此 ORDER BY 语句放在 GROUP BY 行之后,它似乎不起作用,并且最近的同步记录不是结果中数据列旁边显示的记录。

我开始使用的一个更简单的版本具有完全相同的问题,即不一定采用最新的同步记录:

SELECT d.data_id, d.name, d.date_created, s.result, s.details 
FROM data AS d LEFT JOIN sync AS s ON d.data_id = s.data_id 
WHERE s.result = 0 OR s.result IS NULL;

我也尝试过使用子查询来实现这一点,同样的问题:

SELECT d.data_id, d.name, d.date_created, s.sync_id, s.result, s.details
FROM (
    SELECT data_id, name, date_created
    FROM data
) AS d, (
    SELECT s.sync_id, s.data_id, s.result, s.details, s.date_created
    FROM sync AS s, data AS d
    WHERE s.data_id = d.data_id
    ORDER BY s.date_created DESC
) AS s 
WHERE d.data_id = s.data_id 
ORDER BY s.date_created DESC;

请有人建议我如何确定在单个查询中仅获取最新的同步记录以及数据记录。我很高兴该解决方案根据需要包含连接或子查询的任何组合。谢谢你。

4

2 回答 2

2

有几种方法可以做到这一点。这是一个汇总sync表以获取date_created每条data_id记录的最新信息的方法:

SELECT d.data_id, d.name, d.date_created, s.result, s.details 
FROM data AS d LEFT JOIN
     sync AS s
     ON d.data_id = s.data_id LEFT JOIN
     (select s.data_id, max(date_created) as maxdc
      from sync s
      group by s.data_id
     ) smax
     on s.data_id = smax.data_id and s.date_created = smax.maxdc
WHERE s.result = 0 OR s.result IS NULL;
于 2014-04-01T12:09:34.380 回答
1

您只需要在查询中对同步表使用 order by 然后 group by,因为 mysql 在 group by 之前不支持 order by,因为 mysql 使用第一个 group by 然后 order by。

所以你可以使用下面的查询。

SELECT d.data_id, d.name, d.date_created, s.sync_id, s.result, s.details
FROM `data` AS d LEFT JOIN (
  SELECT sync_id, data_id, result, details, date_created FROM (
    SELECT sync_id, data_id, result, details, date_created
    FROM sync
    ORDER BY date_created DESC
  ) a GROUP BY a.data_id
) s
ON d.data_id = s.data_id 
ORDER BY d.date_created DESC;
于 2014-04-01T12:46:38.570 回答