2

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

  1. 标识(整数)
  2. 名称(varchar)
  3. 公司 (int)

假设我有以下数据(仅示例)

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,同时保持与原始搜索词的返回顺序尽可能多的相关性可能的。

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

4

3 回答 3

0

name如果我们可以使用 SQL 标准函数对每个PARTITIONed BY使用 ROW_NUMBER,这将相当容易company。(ROW_NUMBER 给了我们一个“简单的排名”或简单的编号,没有平局也没有差距。)这基本上是@zebediah49 在他的评论中的提议。遗憾的是,MySQL 今天无法做到这一点。

@GordonLindoff 的答案使用自联接技术在 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的用户变量技术很容易搜索,但这里有一个来自另一个 SO 答案的紧凑演示。

现在,如果我们根据公司内的人数对全球幼稚排名进行 MOD,我们将得到“分区排名”,即公司内的相对排名:

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
于 2013-04-16T19:53:02.660 回答
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
于 2013-04-16T15:59:36.397 回答
0

一种可能的解决方案:

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

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

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

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

不是最优雅的解决方案,但它可能会起作用。

于 2013-04-16T16:43:52.940 回答