SQL 查询查找相关结果

问题描述 投票:0回答:3

我有一个带有一个 varchar 列的 sql 表。它包含的一些数据如下:

sadkjlsakjd
Physics Test 2
Test
Test 1
P Test C
Physics Test None
dstestsad

现在,当我使用“Test”关键字搜索时,我需要一个查询,首先给出最相关的记录。我期待着:

Test
Test 1
<Then other records where Test comes in between>

我知道如何使用临时表和交集实现此查询,但对我写的内容一点也不满意。我有一种感觉,应该有一些简单快捷的东西。

请推荐。

谢谢

sql sql-server-2008 t-sql select sql-order-by
3个回答
0
投票

试试这个:

SELECT colName 
FROM tableName 
WHERE colName LIKE '%Test%'
ORDER BY CASE WHEN colName LIKE 'Test%' THEN 1 ELSE 2 END, colName

0
投票

可能是这样的

SELECT * FROM Your_Table WHERE Your_Column LIKE '%Test%'
ORDER BY CASE WHEN Your_Column LIKE 'Test%' THEN 0 ELSE 1 END,Your_Column 

0
投票

我最近正在紧张地研究这个问题,使用 SQL 进行相关性查询。我可能应该写一篇论文或创建一个开源项目,但我工作和家里太忙,所以我会偷懒,我就写在这里。

首先您需要了解相关性计算的准确性取决于您在查询中收集的数据量。因此,您需要权衡性能与准确性。您希望查询的性能越高,您想要读取的数据就越少,但您的结果也会越不准确,因此您需要找到一个平衡点,您的数据会告诉您这一点。

第二您需要将相关性分成单独的标准,并提供一些评分机制,越简单的机制越好,这样就很容易理解,然后您可以从那里进行迭代。听起来很复杂,但其实并不复杂。

解决方案:

  1. 明确您的一组标准
  2. 获取大于请求限制的多个数据样本 3. 对于每种类型的匹配,并分配一个提升因子分数,例如,如果您认为starts_with比contains更相关,您可以说starts_with分数为2,contains分数为1 4.然后
    UNION ALL
    将结果放入单个结果集
  3. 对分数进行汇总并按降序排序。
  4. 根据您的数据调整分数以获得更好的相关性。

注意: 查询额外数据非常重要,因此您可以合并分数,因为一个条件可以以一种方式匹配另一个不同的记录。 越高,结果就越准确,因此请确保查询次数超过请求的限制。

例如,如果您希望限制为 10,那么您可能需要查询至少

limit(10) * number_of_criteria_or_more(2)
=>
TOP(10 * 2)
在我的例子中,我使用了请求行数的 10 倍,这样我可以获得更好的样本和更多相关结果。

使用 CTE(公用表表达式)的示例

-- starts_with criteria data
WITH StartsWith_Criteria_CTE AS (
  SELECT TOP (10 * 2) 2 AS score, test_column FROM test_table WHERE test_column LIKE 'test%'
),
-- contains criteria data
Contains_Criteria_CTE AS (
    SELECT TOP (10 * 2) 1 AS score, test_column FROM test_table WHERE test_column LIKE '%test%'
),
-- combine results using union all
CombinedScores_CTE AS (
   SELECT score, test_column FROM StartsWith_Criteria_CTE
   UNION ALL
   SELECT score, test_column FROM Contains_Criteria_CTE
),
-- Aggregate the scores
AggregatedScores_CTE (
   SELECT
   TOP (10)
     SUM(score) AS score,
     test_column
   FROM CombinedScores_CTE
   GROUP BY test_column
   ORDER BY score DESC
)
-- get your results
SELECT TOP (10) score, test_column FROM AggregatedScores_CTE;

具有简单相关性分数的结果

您将看到 1 代表 contains,3 代表starts_with,因为 contains 和 start_with 重叠。由于这种重叠,有时您需要进行调整以平衡相关性分数。

分数 测试列
3 测试1
3 测试
3 测试C
1 物理测试2
1 dstestsad
1 物理测试 无

这个评分算法很简单,但很有效。 我使用了一个更复杂的分数,该分数基于分数提升因子之上的长度差异,以区分何时存在平局,以保证计算时的正确顺序。

如果您想要更复杂的匹配和决胜计分,那么您可以更新到以下内容。

带有标准平局断路器的示例

-- starts_with criteria data
WITH StartsWith_Criteria_CTE AS (
  SELECT TOP (10 * 2)
    (LEN(test_column)/(LEN(test_column) - LEN('test') + 1.0)) * 2 + 2 AS score, 
    test_column
  FROM test_table WHERE test_column LIKE 'test%'
),
-- contains criteria data
Contains_Criteria_CTE AS (
    SELECT TOP (10 * 2)
     (LEN(test_column)/(LEN(test_column) - LEN('test') + 1.0)) * 1 + 1 AS score, 
     test_column FROM test_table
    WHERE test_column LIKE '%test%'
),
-- combine results using union all
CombinedScores_CTE AS (
   SELECT score, test_column FROM StartsWith_Criteria_CTE
   UNION ALL
   SELECT score, test_column FROM Contains_Criteria_CTE
),
-- Aggregate the scores
AggregatedScores_CTE (
   SELECT
   TOP (10)
     SUM(score) AS score,
     test_column
   FROM CombinedScores_CTE
   GROUP BY test_column
   ORDER BY score DESC
)
-- get your results
SELECT TOP (10) score, test_column FROM AggregatedScores_CTE;

结果与标准决胜分数计算

分数 测试列
15.0 测试
9.0 测试1
9.0 测试C
2.5 dstestsad
2.27 物理测试2
2.21 物理测试 无

似乎有点令人困惑,如果您几乎看不出

dstestsad
在那里,为什么
test
会获得更高的分数?但它确实具有最少的字符数。如果我们认为这是一种奇怪的行为,也许我们应该考虑添加一个新的标准来判断输入是否用作单词

使用条件平局断路器和 is_word 条件的示例

-- starts_with criteria data
WITH StartsWith_Criteria_CTE AS (
  SELECT TOP (10 * 3)
    (LEN(test_column)/(LEN(test_column) - LEN('test') + 1.0)) * 3 + 3 AS score, 
    test_column
  FROM test_table WHERE test_column LIKE 'test%'
),
-- contains criteria data
Contains_Criteria_CTE AS (
    SELECT TOP (10 * 3)
     (LEN(test_column)/(LEN(test_column) - LEN('test') + 1.0)) * 1 + 1 AS score, 
     test_column FROM test_table
    WHERE test_column LIKE '%test%'
),
-- is a word criteria data
IsAWord_Criteria_CTE AS (
    SELECT TOP (10 * 3)
     (LEN(test_column)/(LEN(test_column) - LEN('test') + 1.0)) * 2 + 2 AS score, 
     test_column FROM test_table
    WHERE
      test_column LIKE 'test %' OR
      test_column LIKE '% test %' OR
      test_column LIKE '% test' OR
      test_column = 'test'
),
-- combine results using union all
CombinedScores_CTE AS (
   SELECT score, test_column FROM StartsWith_Criteria_CTE
   UNION ALL
   SELECT score, test_column FROM Contains_Criteria_CTE
   UNION ALL
   SELECT score, test_column FROM IsAWord_Criteria_CTE
),
-- Aggregate the scores
AggregatedScores_CTE (
   SELECT
   TOP (10) 
     SUM(score) AS score,
     test_column
   FROM CombinedScores_CTE
   GROUP BY test_column
   ORDER BY score DESC
)
-- get your results
SELECT score, test_column FROM AggregatedScores_CTE;

附加结果是一个词标准

现在结果似乎与用户非常相关。

分数 测试列
30.0 测试
18.0 测试1
18.0 测试C
6.82 物理测试2
6.64 物理测试 无
2.5 dstestsad

简单的方法

在您的情况下,您只有 2 个条件,并且

starts_with
contains
重叠,如果数据相当小,您可能可以依靠
UNION
的顺序来获取所有数据。

例如:

SELECT test_column FROM test_table WHERE test_column LIKE 'test%'
UNION ALL
SELECT test_column FROM test_table WHERE test_column LIKE '%test%' AND NOT test_column LIKE 'test%'
© www.soinside.com 2019 - 2024. All rights reserved.