跨多个表的MySQL查询文本

时间:2019-03-18 22:10:45

标签: mysql sql

我有两个MySQL表;城市和国家/地区,我希望允许用户在两​​个表中搜索其中一个匹配项,并且希望从两个表中获得质量匹配/相关性顺序。

(SELECT 'city' AS type, c.slug, c.name, c.city_id AS id 
FROM city c 
WHERE c.name LIKE '%ame%' 
ORDER BY CASE 
  WHEN c.name = 'ame' THEN 0
  WHEN c.name LIKE 'ame%' THEN 1 
  WHEN c.name LIKE '%ame%' THEN 2
  WHEN c.name LIKE '%ame' THEN 3 
  ELSE 4 END,
  c.name ASC
LIMIT 24 OFFSET 0)
UNION
(SELECT 'country' as type, c.slug, c.name, c.country_id AS id 
FROM country c 
WHERE c.name LIKE '%ame%'
ORDER BY CASE
  WHEN c.name = 'ame' THEN 0
  WHEN c.name LIKE 'ame%' THEN 1
  WHEN c.name LIKE '%ame%' THEN 2
  WHEN c.name LIKE '%ame' THEN 3
  ELSE 4 END,
  c.name ASC 
LIMIT 24 OFFSET 0);

我在两个表格中得到一个合并的结果,但是我得到了所有城市的结果,然后是所有国家的结果-我想得到它,以便将结果按准确性进行混合和排序...而不是城市的准确性,然后国家的准确性-还是可取的?

尤其欢迎使用其他方法在两个表之间完成查询,理想情况下,我可能需要将一个表连接到城市,将一个表连接到国家,以将一些元信息添加到返回的数据中。

还是有更好的方法来调用两个端点并具有关联性匹配列,然后将两个端点合并到以此关联性排序的json阵列服务器端?

1 个答案:

答案 0 :(得分:1)

您可以将UNION包装到子查询中,然后再次进行排序:

SELECT *
FROM ((SELECT 'city' AS type, c.slug, c.name, c.city_id AS id 
       FROM city c 
       WHERE c.name LIKE '%ame%' 
       ORDER BY CASE 
         WHEN c.name = 'ame' THEN 0
         WHEN c.name LIKE 'ame%' THEN 1 
         WHEN c.name LIKE '%ame%' THEN 2
         WHEN c.name LIKE '%ame' THEN 3 
         ELSE 4 END,
         c.name ASC
       LIMIT 24 OFFSET 0)
       UNION
       (SELECT 'country' as type, c.slug, c.name, c.country_id AS id 
       FROM country c 
       WHERE c.name LIKE '%ame%'
       ORDER BY CASE
         WHEN c.name = 'ame' THEN 0
         WHEN c.name LIKE 'ame%' THEN 1
         WHEN c.name LIKE '%ame%' THEN 2
         WHEN c.name LIKE '%ame' THEN 3
         ELSE 4 END,
         c.name ASC 
       LIMIT 24 OFFSET 0)) c
ORDER BY CASE
  WHEN c.name = 'ame' THEN 0
  WHEN c.name LIKE 'ame%' THEN 1
  WHEN c.name LIKE '%ame%' THEN 2
  WHEN c.name LIKE '%ame' THEN 3
  ELSE 4 END,
  c.name ASC 

创建排名列会更有效:

SELECT *
FROM ((SELECT 'city' AS type, c.slug, c.name, c.city_id AS id,
       CASE 
         WHEN c.name = 'ame' THEN 0
         WHEN c.name LIKE 'ame%' THEN 1 
         WHEN c.name LIKE '%ame%' THEN 2
         WHEN c.name LIKE '%ame' THEN 3 
         ELSE 4 END AS `rank`
       FROM city c 
       WHERE c.name LIKE '%ame%' 
       ORDER BY `rank`, c.name ASC
       LIMIT 24 OFFSET 0)
       UNION
       (SELECT 'country' as type, c.slug, c.name, c.country_id AS id,
       CASE 
         WHEN c.name = 'ame' THEN 0
         WHEN c.name LIKE 'ame%' THEN 1 
         WHEN c.name LIKE '%ame%' THEN 2
         WHEN c.name LIKE '%ame' THEN 3 
         ELSE 4 END AS `rank` 
       FROM country c 
       WHERE c.name LIKE '%ame%'
       ORDER BY `rank`, c.name ASC 
       LIMIT 24 OFFSET 0)) c
ORDER BY c.rank, c.name ASC

这将为您提供48个结果,每个城市和国家/地区都有24个结果。如果您只想获得排名靠前的结果,而不管它们来自哪个表,只需从ORDER BY中删除LIMITUNION子句:

SELECT *
FROM ((SELECT 'city' AS type, c.slug, c.name, c.city_id AS id 
       FROM city c 
       WHERE c.name LIKE '%ame%')
       UNION
       (SELECT 'country' as type, c.slug, c.name, c.country_id AS id 
       FROM country c 
       WHERE c.name LIKE '%ame%'
       )) c
ORDER BY CASE
  WHEN c.name = 'ame' THEN 0
  WHEN c.name LIKE 'ame%' THEN 1
  WHEN c.name LIKE '%ame%' THEN 2
  WHEN c.name LIKE '%ame' THEN 3
  ELSE 4 END,
  c.name ASC 
LIMIT 48 OFFSET 0