【问题标题】:Sorting SQL Server records by number of OR conditions matched按匹配的 OR 条件数对 SQL Server 记录进行排序
【发布时间】:2013-11-20 20:06:11
【问题描述】:

假设我有一个(代码生成的)查询,它在许多不同的字段中查找关键字。例如,术语UniversitySouthAfrica 中的任何一个可能位于名称字段、地址字段或某个其他字段中。我想查找这些字段中的任何一个与这些关键字中的任何一个匹配的所有记录:

SELECT *
FROM
    Institutions
WHERE
    Institutions.name LIKE '%University%' OR
    Institutions.address LIKE '%University%' OR
    Institutions.name LIKE '%South%' OR
    Institutions.address LIKE '%South%' OR
    Institutions.name LIKE '%Africa%' OR
    Institutions.address LIKE '%Africa%'

但是,这将拉起一切。我想按最符合条件的记录进行排序。

我认为这可行,但看起来很笨重:

SELECT *
FROM
    Institutions
WHERE
    Institutions.name LIKE '%University%' OR
    Institutions.address LIKE '%University%' OR
    Institutions.name LIKE '%South%' OR
    Institutions.address LIKE '%South%' OR
    Institutions.name LIKE '%Africa%' OR
    Institutions.address LIKE '%Africa%'
ORDER BY
    (
        CASE WHEN Institutions.name LIKE '%University%' THEN 1 ELSE 0 END +
        CASE WHEN Institutions.address LIKE '%University%' THEN 1 ELSE 0 END +
        CASE WHEN Institutions.name LIKE '%South%' THEN 1 ELSE 0 END +
        CASE WHEN Institutions.address LIKE '%South%' THEN 1 ELSE 0 END +
        CASE WHEN Institutions.name LIKE '%Africa%' THEN 1 ELSE 0 END +
        CASE WHEN Institutions.address LIKE '%Africa%' THEN 1 ELSE 0 END
    ) DESC

有更清洁的东西吗?我可以使用特定于 SQL Server 的解决方案,但纯 SQL 解决方案会很棒。

【问题讨论】:

    标签: sql sql-server sql-like


    【解决方案1】:

    您的解决方案对我来说看起来不错,但这里还有一些应该可以工作的东西(伪代码):

    SELECT * FROM
    (SELECT *,COUNT(*) AS cnt FROM
    (SELECT * FROM I
    WHERE name LIKE '%etc%'
    UNION ALL
    SELECT * FROM I
    WHERE name LIKE '%etc2%'
    -- etc. )
    GROUP BY *)
    ORDER BY cnt DESC;
    

    【讨论】:

    • 是的,我也考虑过使用 UNIONs + COUNT,但我认为这在可读性方面并没有提高。我也想知道执行时间;我在想,对已经过滤的数据使用 case 语句必须比一堆 UNION 更快。
    【解决方案2】:

    你可以在 sqlserver 中使用全文搜索排名,但我认为这有点矫枉过正......

    反正几个指针:

    http://technet.microsoft.com/en-us/library/ms142524%28v=sql.105%29.aspx

    http://technet.microsoft.com/en-us/library/cc879245.aspx

    或者,如果您从返回计数的 case-when 事物创建一个函数,您可以在 where 中使用相同的函数。 (这也是hacky...)

    【讨论】:

      【解决方案3】:

      可能是这样的:

      SELECT * FROM (
          SELECT i.*,
          (
            CASE WHEN i.name LIKE '%University%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%University%' THEN 1 ELSE 0 END +
            CASE WHEN i.name LIKE '%South%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%South%' THEN 1 ELSE 0 END +
            CASE WHEN i.name LIKE '%Africa%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%Africa%' THEN 1 ELSE 0 END
          ) AS rnk
          FROM Institutions i 
       ) result
       WHERE result.rnk > 0
       ORDER BY result.rnk DESC
      

      编辑:我忘了Apply

      SELECT *
      FROM
          Institutions i
      CROSS APPLY
      (
            SELECT
           (CASE WHEN i.name   LIKE '%University%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%University%' THEN 1 ELSE 0 END +
            CASE WHEN i.name    LIKE '%South%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%South%' THEN 1 ELSE 0 END +
            CASE WHEN i.name    LIKE '%Africa%' THEN 1 ELSE 0 END +
            CASE WHEN i.address LIKE '%Africa%' THEN 1 ELSE 0 END) as rnk
      ) c
      ORDER BY c.rnk DESC
      

      Small example

      【讨论】:

      • 这接近于我重构原始解决方案的方式。
      • @JordanReiter 我认为已经晚了,但我记得这个问题并添加另一个解决方案。
      猜你喜欢
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多