2

我有一个使用联合来连接两个子查询的查询,例如

SELECT * FROM posts WHERE postTypeId=1 (e.g. blog)
UNION
SELECT * FROM posts WHERE postTypeId=2 (e.g. news)

这种方法生成的结果集依次定位两个子集(“博客”然后是“新闻”)。

我想创建一个将两者交错的结果集,在“博客”子集和“新闻”子集的行之间交替。

我觉得必须有一个简单的方法来做到这一点,但我没有找到它。

任何建议将不胜感激。

缺口

4

4 回答 4

4

这是最适合我的解决方案。它与当前的任何提案都不相同,因此我独立添加了它。@a、@b 和@c 用于为每个子集创建行号,这意味着在组合结果中,3 行将共享相同的行号(“行集”)。这用作一阶排序,然后二阶排序对“行集”中的行进行排序。

SET @a = 0;
SET @b = 0;
SET @c = 0; 

SELECT * FROM(
  SELECT @a := @a + 1 AS sortOne, 1 AS sortTwo, posts.* FROM posts WHERE posts.postTypeId=3
    UNION
  SELECT @b := @b + 1 AS sortOne, 2 AS sortTwo, posts.* FROM posts WHERE posts.postTypeId=2
    UNION
  SELECT @c := @c + 1 AS sortOne, 3 AS sortTwo, posts.* FROM posts WHERE posts.postTypeId=1
) AS result ORDER BY sortOne, sortTwo

该解决方案是由提交的解决方案派生/启发的,但我认为将它们中的任何一个标记为本身是可接受的解决方案是不合适的。所以,感谢 Thomas Clayson、Tony Hopkinson 和 rmunoz,他们的答案我投了赞成票。干杯!

于 2012-09-05T15:13:04.433 回答
2

好吧,这是我能想到的一种新颖的方法(未经测试,但您会明白要点):

SELECT * FROM (
    SELECT 1 AS query, @n := @n + 1 AS rowNumber, posts.* FROM (select @n:=0), posts WHERE posts.postTypeId=1
    UNION
    SELECT 2 AS query, @n := @n + 1 AS rowNumber, posts.* FROM (select @n:=0), posts WHERE posts.postTypeId=2
) ORDER BY rowNumber, query;

因此,这将执行两个查询,然后按 firstrowNumber和 by排序query。你最终会得到类似的东西:

rowNumber | query
1         | 1
1         | 2
2         | 1
2         | 2
etc...

SELECT @n=:0将查询的全局变量重置n为 0,然后@n := @n + 1递增每一行的值。

如果您需要更多解释,请告诉我。我希望这行得通!:)

于 2012-09-05T08:56:27.193 回答
2

尝试

Set @current_row = 0
SELECT * FROM (
  SELECT @current_row := @current_row + 1 as Position, posts.*
    FROM posts
    WHERE postTypeId=1
  UNION 
  SELECT @current_row, posts.*
    FROM posts
    WHERE postTypeId=2
) dummyTableName
ORDER BY position, postTypeId

也许

于 2012-09-05T08:57:04.033 回答
2

这很简单,你可以在你的子查询中添加一个参数,参数“rank”,这样:

SET @rank=0;
SELECT @rank:=@rank+2 AS rank FROM posts WHERE postTypeId=1 (e.g. blog)

然后,你得到:

0, ...
2, ...

如果您在另一个查询中执行相同操作,但将 rank 初始化为 1,您将得到:

1, ...
3, ...

最后“ORDER BY rank”,你会得到混合的帖子和新闻。

于 2012-09-05T08:59:00.430 回答