Question

This seems to be a convoluted problem, but I'll try my best to articulate the idea and illustrate a scenario. Essentially I have two tables that need to be combined and returned as the result set for a single query. One table needs to be merged into the other in a specific order.

Say table one is called Articles and table two is called Features. Both tables have an ID field with unique numbers. Articles has a date field which will be used to initially sort its records in descending order. The Features table has a Delta field which be used initially to sort its records. Some of the records in the Features table are placeholders and are not meant to be included in the final set. Their only purpose is to affect the sort order. Each record has a unique value in the Delta field, from 1 - X which will be used to sort these records. Another field called Skip has a value of 1 if it should be eliminated when merging the two tables together. Again, the only purpose to the skipped records is to take up space during the initial sort on the Features table. Even though they are unnecessary, they exist and can't be deleted.

The tricky part is that when the results from both tables are merged, any non-skipped records from the Features table need to be inserted into the results from the Articles table in the exact order they appears in the Features table.

So lets say I have 6 records in the Features table, A - F and the order field ranges from 1 - 6. Records A,B,D,E all have a value of 1 in the Skip field. That means I'm only interested in records C and F both of which need to be inserted into the final record set in positions 3 and 6 respectively.

The records may look something like this for the Articles table:

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

The Features table may look something like this:

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

The results would look something like this (not including any additional fields that might be needed to achieve my goal):

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

Hope my explanation makes sense. Any ideas?

Thanks, Howie

Was it helpful?

Solution 2

Looks like this example in SQL Fiddle did it for me.

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

Thanks to Kordirko for the framework.

OTHER TIPS

I assume that there is a mistake in your example - record id=16 is sixth row in Features table, so should be after id=5 in results, not before.

Try the blelow query. Here is 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top