MySQL试图返回交错的结果

时间:2013-04-16 15:57:16

标签: mysql sql database search

例如,我有一个包含三个字段的表:

  1. id(int)
  2. name(varchar)
  3. company(int)
  4. 假设我有以下数据(仅限示例)

    id ---    name          ---    company
    ---------------------------------------
    1 ---    John Baker     ---      1
    2 ---    Ann Johnson    ---      1
    3 ---    John Wu        ---      1
    4 ---    Mike Johns     ---      2
    5 ---    John John      ---      2
    6 ---    Johnny Boy     ---      2
    

    我想对名称进行搜索,并返回公司错开的数据。因此,如果我在LIKE '%John%'上执行搜索,我希望按照公司排序的方式返回数据,如:1,2,1,2,1,2,同时保持尽可能多的相关性。原始搜索词尽可能。

    我不知道如何以这种交错的方式返回数据,我已经考虑了好几个小时了。如果有人能帮助我,我很乐意听到他们的想法!

3 个答案:

答案 0 :(得分:0)

如果您希望按公司排序:

select *
from t
where . . .
order by company, id;

如果您希望它交错,那么公司内的计数器会有所帮助。这是一种方式:

select t.*
from (select *,
             (select count(*) from t t2 where <where clause on t2 here> and t2.comapny = t.company and t2.id < t.id) as seqnum
      from t
      where . . .
    ) t
order by seqnum, company

答案 1 :(得分:0)

一种可能的解决方案:

select *
from yourTable
where ...
order by ((company*1000) + id);

根据需要添加尽可能多的零。至少,你需要与这个数字一样多的零:

select pow(10,length(max(company))) from yourTable;

如果您在此查询中提取大量记录,则排序可能会非常慢,因此我建议您使用最佳where条件。

不是最优雅的解决方案,但可能有效。

答案 2 :(得分:0)

如果我们可以将每个name PARTITIONed BY company的SQL标准函数用于ROW_NUMBER,那么这将非常简单。 (ROW_NUMBER给了我们一个“天真的排名”或简单的编号,没有任何关系,也没有差距。)这基本上是@ zebediah49在他的评论中提出的建议。可悲的是,MySQL今天无法做到这一点。

@GordonLindoff's answer使用自连接技术在MySQL中模拟此功能。这是另一种做同样的方法。

首先,我们按公司对每个人进行分组,然后使用用户变量全局天真地对它们进行排名。因此,A公司的三个人成为#1,#2和#3,B公司的两个人成为#4和#5,依此类推:

company | name     == ROW_NUMBER()d after ==>  company | name    | rank
--------+--------  == GROUP BY `company`  ==>  --------+---------+------
    A   | Alice                                    A   | Alice   | 1
    B   | Bob                                      A   | Charlie | 2
    A   | Charlie                                  A   | Deborah | 3
    A   | Deborah                                  B   | Bob     | 4
    B   | Erwin                                    B   | Erwin   | 5

用于在MySQL中模拟ROW_NUMBER的用户变量技术很容易搜索,但这是来自another SO answer的紧凑演示。

现在,如果我们根据公司内部的人数调整全球天真等级,我们会得到一个“分区等级”,即公司内部的相对等级:

company | name     | rank | npeople | rank % npeople
--------+----------+------+---------+----------------
    A   | Alice    |  1   |  3      | 1
    A   | Charlie  |  2   |  3      | 2
    A   | Deborah  |  3   |  3      | 0
    B   | Bob      |  4   |  2      | 0
    B   | Erwin    |  5   |  2      | 1

将所有内容放在一起,加入查询以计算每家公司的人数,我们得到:

  SELECT id, name, ranked.company
    FROM (  SELECT tbl.id, tbl.name, tbl.company, (@rn := @rn + 1) AS rn
              FROM tbl
              JOIN (SELECT @rn := 0) vars
             WHERE tbl.name LIKE '%John%'
          ORDER BY company) ranked
    JOIN (SELECT company, COUNT(id) AS npeople FROM tbl GROUP BY company) companies
         ON ranked.company = companies.company
ORDER BY rn MOD companies.npeople, company