【问题标题】:MySQL Combining Tables Specific OrderMySQL 组合表特定顺序
【发布时间】:2013-07-29 02:56:02
【问题描述】:

这似乎是一个令人费解的问题,但我会尽力阐明这个想法并说明一个场景。本质上,我有两个表需要组合并作为单个查询的结果集返回。一个表需要按特定顺序合并到另一个表中。

假设表一称为Articles,表二称为Features。两个表都有一个带有唯一编号的 ID 字段。 Articles 有一个日期字段,该字段将用于最初按降序对其记录进行排序。 Features 表有一个 Delta 字段,最初用于对其记录进行排序。 Features 表中的一些记录是占位符,并不意味着包含在最终集合中。它们的唯一目的是影响排序顺序。每条记录在 Delta 字段中都有一个唯一值,从 1 - X 将用于对这些记录进行排序。另一个名为 Skip 的字段的值为 1,如果在将两个表合并在一起时应该将其删除。同样,跳过记录的唯一目的是在 Features 表的初始排序期间占用空间。即使它们是不必要的,它们也存在并且不能被删除。

棘手的部分是,当合并两个表的结果时,Features 表中的任何未跳过的记录都需要插入到 Articles 的结果中表中它们出现在Features表中的确切顺序。

假设我在 Features 表中有 6 条记录,A - F 和 order 字段范围为 1 - 6。记录 A、B、D、E 在跳过字段。这意味着我只对记录 C 和 F 感兴趣,这两个记录都需要分别插入到位置 3 和 6 的最终记录集中。

Articles 表的记录可能如下所示:

+----+------------+
| id |    date    | 
+----+------------+
| 1  | 9999999999 |
+----+------------+
| 2  | 9999999998 |
+----+------------+
| 3  | 9999999997 |
+----+------------+
| 4  | 9999999996 |
+----+------------+
| 5  | 9999999995 |
+----+------------+
| 6  | 9999999994 |
+----+------------+
| 7  | 9999999993 |
+----+------------+
| 8  | 9999999992 |
+----+------------+
| 9  | 9999999991 |
+----+------------+
| 10 | 9999999990 |
+----+------------+

Features 表可能如下所示:

+----+------+-------+------+
| id | name | delta | skip |
+----+------+-------+------+
| 11 |   A  |   1   |   1  |
+----+------+-------+------+
| 12 |   B  |   2   |   1  |
+----+------+-------+------+
| 13 |   C  |   3   |   0  |
+----+------+-------+------+
| 14 |   D  |   4   |   1  |
+----+------+-------+------+
| 15 |   E  |   5   |   1  |
+----+------+-------+------+
| 16 |   F  |   6   |   0  |
+----+------+-------+------+

结果将如下所示(不包括实现我的目标可能需要的任何其他字段):

+----+
| id |
+----+
| 1  |
+----+
| 2  |
+----+
| 13 | (record from the Features table in the third position)
+----+
| 3  |
+----+
| 4  |
+----+
| 16 | (record from the Features table in the sixth position)
+----+
| 5  |
+----+
| 6  |
+----+
| 7  |
+----+
| 8  |
+----+
| 9  |
+----+
| 10 |
+----+

希望我的解释是有道理的。有什么想法吗?

谢谢, 豪伊

【问题讨论】:

  • SQL 表本质上是无序的。因此,插入的顺序无关紧要。您需要考虑一个单独的列来存储排序。
  • 我正在考虑这样做并向 Features 表添加一个标志,以便它们始终在 Articles 表中具有相同 Order 值的记录之前排序,但这是我的问题。如果 Articles 表有一个带有数字 1-10 的 Order 字段,并且我尝试合并这两个表,我将有两条记录,其中 Order = 3 和 Order = 6,一条来自 Articles,一条来自 Features。虽然最终集中的第 3 条记录可能是 Features 表中的记录,但第 6 条实际上是 Articles 表中的第 5 条记录。第 1 条、第 2 条、第 3 条、第 3 条、第 4 条、第 5 条、第 6 条、第 6 条……WTF?

标签: mysql merge sql-order-by records


【解决方案1】:

我假设您的示例中有一个错误 - 记录 id=16 是 Features 表中的第六行,因此应该在结果中的 id=5 之后,而不是之前。

试试 blelow 查询。这里是SQLFiddle

select id from (
  select `date`, null delta, id
  from Articles
  union all
  select a.`date`, f.delta, f.id 
  from ( 
    select (@x:=@x+1) rn, a.*
    from Articles a, (select @x:=0) z
    order by a.`date` desc
  ) a
  join (
    select (@y:=@y+1) rn, f.id, f.delta, f.skip
    from Features f, (select @y:=0) z
    order by f.delta
  ) f
  on a.rn = f.rn
  where f.skip <> 1
  order by `date` desc, isnull( delta ), delta 
) merge

【讨论】:

  • 你是对的,那是我的错误。该解决方案非常出色,但是,它没有考虑到预期的插入位置。虽然 ID 13 确实出现在第 3 个,但 ID 16 应该出现在第 6 个,而是出现在第 7 个。
【解决方案2】:

看起来 this example in SQL Fiddle 是帮我做的。

SELECT id, sort_order FROM (
SELECT `date`, NULL delta, id, (@a_count:=@a_count+1) sort_order
  FROM Articles a_main, (SELECT @a_count:=-1) z

  UNION ALL

SELECT a.`date`, f.delta, f.id, f.weighted_rn
  FROM (
    SELECT (@x:=@x+1) rn, a.*
    FROM Articles a, (SELECT @x:=-1) z
    ORDER BY a.`date` DESC
  ) a

JOIN (
    SELECT (@y:=@y+1) rn, TRUNCATE((f.delta - @y - (1/@y)),2) AS weighted_rn, f.id, f.delta, f.skip
    FROM Features f, (SELECT @y:=-1) z
    WHERE f.skip <> 1
    ORDER BY f.delta
  ) f

ON a.rn = f.rn
ORDER BY sort_order
) merge

感谢 Kordirko 提供的框架。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多