MySQL组合表特定顺序

时间:2013-07-29 02:56:02

标签: mysql merge sql-order-by records

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

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

棘手的部分是,当两个表的结果合并时,功能表中的任何非跳过记录都需要插入文章的结果中表格按照它们在功能表格中显示的确切顺序。

假设我在功能表中有6条记录,A - F和顺序字段的范围是1 - 6.记录A,B,D,E的值均为1 in Skip 字段。这意味着我只对记录C和F感兴趣,这两个记录都需要分别插入位置3和6的最终记录集中。

对于文章表格,记录可能如下所示:

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

功能表可能如下所示:

+----+------+-------+------+
| 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 |
+----+

希望我的解释有意义。有什么想法吗?

谢谢, 豪伊

2 个答案:

答案 0 :(得分:0)

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

尝试流失查询。这是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

答案 1 :(得分:0)

看起来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