代码之家  ›  专栏  ›  技术社区  ›  Mad Scientist

按其组件单独排序的联合查询

  •  1
  • Mad Scientist  · 技术社区  · 7 年前

    SELECT name FROM data WHERE name ILIKE '%xyz%' ORDER BY other_column LIMIT 100;
    

    我真正想要实现的是将匹配的行放在前面name列的开头。所以总共仍然有100行,但第一行是根据匹配的结果填充的 name ILIKE 'xyz% ,然后使用 ILIKE '%xyz%' .

    我试图通过如下的联合查询来实现这一点

    SELECT name FROM data WHERE name ILIKE 'xyz%' 
    UNION
    SELECT name FROM data WHERE name ILIKE '%xyz%'
    ORDER BY other_column 
    LIMIT 100;
    

    这显然不起作用,因为它是按 other_column . 我最初的想法是在每个查询中添加一列用于排序

    SELECT 1 as sort_order, name FROM data WHERE name ILIKE 'xyz%' 
    UNION
    SELECT 2 as sort_order, name FROM data WHERE name ILIKE '%xyz%'
    ORDER BY sort_order, other_column 
    LIMIT 100;
    

    但这就扼杀了重复删除 UNION 而是表现得像 UNION ALL 因为我添加了sort_order列,使原本相同的行变得不同。

    当然,我可以在数据库之外的稍后步骤中删除重复项,但这对我来说不是一个非常吸引人的解决方案。有没有办法分别对联合查询的各个部分进行排序,并实现我描述的结果?

    2 回复  |  直到 7 年前
        1
  •  1
  •   klin    7 年前

    使用函数 position(substring in string) 而不是联合,例如:

    WITH data(name, other_column) AS (
    VALUES
        ('abc xyz', 1),
        ('xyz abc', 2),
        ('a xyz b', 3),
        ('xyz abc', 4)
    )
    
    SELECT name, other_column
    FROM data 
    WHERE name ILIKE '%xyz%'
    ORDER BY position('xyz' in name), other_column
    LIMIT 100;
    
      name   | other_column 
    ---------+--------------
     xyz abc |            2
     xyz abc |            4
     a xyz b |            3
     abc xyz |            1
    (4 rows)
    

    或:

    SELECT name, other_column
    FROM data 
    WHERE name ILIKE '%xyz%'
    ORDER BY position('xyz' in name) > 1, other_column
    LIMIT 100;
    
      name   | other_column 
    ---------+--------------
     xyz abc |            2
     xyz abc |            4
     abc xyz |            1
     a xyz b |            3
    (4 rows)    
    
        2
  •  0
  •   forpas    7 年前

    利用 other_column :

    SELECT t.name FROM (
        SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
        UNION
        SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
    ) AS t
    ORDER BY t.other_column 
    LIMIT 100;
    

    name 在第一个列表中创建 其他专栏 .
    是一样的 名称 .
    最后分类