MySQL - 通过总LIMIT在UNION中选择等量的每个

时间:2017-12-04 14:00:19

标签: mysql union sql-limit

在MySQL数据库中,我有3个表:customersprojectstasks。对于我正在实现的搜索,我想搜索所有3个表并选择找到的匹配项。问题是我想同样限制MySQL返回的结果数量。

这是我目前拥有的查询示例:

SELECT id, title, type
FROM (
    (
    SELECT id, title, 'customer' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM customers
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (
    SELECT id, title, 'project' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM projects
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (
    SELECT id, title, 'task' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM tasks
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
) res
LIMIT 6;

在这个例子中,我想将结果限制为6。

我希望这个例子的结果如下:

1)如果所有表格至少有2个结果,则每个表格显示2个结果。

id     title                      type
20     'First test customer'      'customer'
22     'Test customer 2'          'customer
48     'A project for testing'    'project'
17     'Test Project'             'project'
1      'Task test'                'task'
2      'Second test'              'task'

2)如果一个表没有任何结果,则显示其他2个表中每个表的3个结果。 (如果只有一个表有结果,则显示该表的6个结果。)

id     title                      type
20     'First test customer'      'customer'
22     'Test customer 2'          'customer
56     'Customer test 56'         'customer'
1      'Task test'                'task'
2      'Second test'              'task'
3      'Test task'                'task'

3)如果2个表中有2个以上的结果,而第3个表只有1个结果,则显示3个结果,其中一个表具有足够的结果,2个结果表示另外两个表,1表示结果表只有1个结果。

id     title                      type
20     'First test customer'      'customer'
48     'A project for testing'    'project'
17     'Test Project'             'project'
34     'Testing project'          'project'
1      'Task test'                'task'
2      'Second test'              'task'

有人可以帮我解决这个问题吗?

提前致谢!

2 个答案:

答案 0 :(得分:1)

您可以为每个SELECT使用行号,然后使用该计算字段对UNION进行排序,以平衡从单个查询中获得的结果(我未测试此代码,请参加它作为一个起点):

SET @rank1=0;
SET @rank2=0;
SET @rank3=0;
SELECT id, title, type, rank
FROM (
    (

    SELECT @rank1:=@rank1+1 AS rank, id, title, 'customer' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM customers
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (

    SELECT @rank2:=@rank2+1 AS rank, id, title, 'project' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM projects
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (

    SELECT @rank3:=@rank3+1 AS rank, id, title, 'task' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM tasks
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
) res
ORDER BY rank 
LIMIT 6;

答案 1 :(得分:1)

要在不声明@rankX变量的情况下将@ kiks73结果放在一个查询中,可以在from子句中添加(SELECT @rankX:=0) AS t。像这样:

SELECT id, title, type, rank
FROM (
    (

    SELECT @rank1:=@rank1+1 AS rank, id, title, 'customer' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM customers,(SELECT @rank1:=0) AS t
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (

    SELECT @rank2:=@rank2+1 AS rank, id, title, 'project' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM projects,(SELECT @rank2:=0) AS t
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
    UNION DISTINCT
    (

    SELECT @rank3:=@rank3+1 AS rank, id, title, 'task' AS type, MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE) AS score
    FROM tasks,(SELECT @rank3:=0) AS t
    WHERE MATCH (title) AGAINST ('+test* ' IN BOOLEAN MODE)
    )
) res
ORDER BY rank
LIMIT 6;