SQL服务器:基于2个明细表的相似记录
SQL Server: similar records based on 2 detail tables
我需要在 SQL Server 2016 中找到类似的记录,如果我能根据它们的匹配程度对结果进行排序,那就太好了。
类似的匹配条件是 2 个细节 tables.
我的table结构是:
//Basic:
Id Title
1 Title 1
2 Title 2
3 Title 3
4 Title 4
5 Title 5
//Parameters:
Id Title
1 Param 1
2 Param 2
3 Param 3
4 Param 4
5 Param 5
//Values:
Id Value
1 Val 1
2 Val 2
3 Val 3
4 Val 4
5 Val 5
与连接tables:
BasicId ParameterId ValueId
1 1 2
1 3 1
1 4 5
2 1 1
2 2 4
2 3 2
3 1 2
3 3 1
3 4 4
4 1 2
4 4 2
4 5 2
5 1 1
5 2 5
5 3 3
在我的程序中的某个时刻,我使用参数和值创建了新的基本行(在内存中)。现在我需要知道:
- 数据库中是否有完全匹配相同参数和值的记录。
- 相似记录按匹配的参数和值的数量排序。
对于第一点,我是这样做的:
如果所有参数和值匹配,则 2 行相等。
现在我用所有参数和值的 ID 计算字符串并将其添加到 Basic table.
基本变为:
Id Title EqualString (this comes from connection table)
1 Title 1 1:2;3:1;4:5
2 Title 2 1:1;2:4;3:2
3 Title 3 1:2;3:1;4:4
4 Title 4 1:2;4:2;5:2
5 Title 5 1:1;2:5;3:3
效果很好,因为顺序是由 ParameterId ASC 定义的,而且我在 EqualString 列上有索引。在这一点上我应该说,我的基本 table 有大约 500 万条记录并且还在增长。
但是对于第二个问题,我不知道如何解决这种问题。
例如:
Input Title X1 1:1;2:4;3:2 100% Title 2
33% Title 5
Input Title X2 1:1;2:4;3:1 66% Title 2
33% Title 5
Input Title X3 1:2;3:1;5:5 66% Title 1
66% Title 3
Input Title X4 1:2;3:1;5:3 66% Title 3
33% Title 5
我使用 SQL Server 2016 并且可以完全控制安装数据库的计算机。
大约有 100 个参数值要检查它们是否匹配(在上面的示例中只有 3 个 - 它们用 ; 分隔)
我认为全文搜索不是答案(或者也许是),因为我需要 2 个逗号之间的精确匹配(例如 2:5)。
或者我应该采用完全不同的方法而不计算 EqualString(在插入 时很少)。
用例:
我正在构建销售动态产品的网页。这意味着,该用户在购买前对其进行配置。
例如:设置高度、宽度、颜色,选择material ...
现在我需要知道这个产品是否已经存在(其他人选择完全相同的参数(宽度、高度、颜色)和值(100、120、绿色)或者这是全新的产品。
配置的参数在参数 table 中,值在值 table.
中
测试数据
这是从问题中逐字复制的:
CREATE TABLE #Connection( BasicId INT, ParameterId INT, ValueId INT )
INSERT INTO #Connection
VALUES
( 1, 1, 2 ), ( 1, 3, 1 ), ( 1, 4, 5 ),
( 2, 1, 1 ), ( 2, 2, 4 ), ( 2, 3, 2 ),
( 3, 1, 2 ), ( 3, 3, 1 ), ( 3, 4, 4 ),
( 4, 1, 2 ), ( 4, 4, 2 ), ( 4, 5, 2 ),
( 5, 1, 1 ), ( 5, 2, 5 ), ( 5, 3, 3 )
这是新产品的示例数据
CREATE TABLE #NewConnection( BasicId INT, ParameterId INT, ValueId INT )
INSERT INTO #NewConnection
VALUES
( 10, 1, 2 ), ( 10, 2, 2 ), ( 10, 3, 1 ),
( 11, 1, 1 ), ( 11, 2, 4 ), ( 11, 3, 2 ),
( 12, 1, 0 ), ( 12, 2, 5 ), ( 12, 3, 3 )
查询
SELECT NC.BasicID AS NewBasicID, C.BasicID, C.ParameterId, C.ValueId,
CONVERT( DECIMAL( 5, 0 ), COUNT( C.ParameterId ) OVER( PARTITION BY NC.BasicID, C.BasicID )) / ParamCount * 100 AS MatchStrength
FROM
( SELECT *, COUNT( ParameterId ) OVER( PARTITION BY BasicID ) AS ParamCount
FROM #NewConnection ) AS NC
INNER JOIN #Connection AS C
ON NC.ParameterId = C.ParameterId AND C.ValueId = NC.ValueId
ORDER BY NewBasicID, MatchStrength DESC, C.BasicID, C.ParameterId
工作原理
#NewConnection
- 包含需要根据现有 #Connection
table 检查的 "New Connection" 数据
ParamCount
- 计算每个 "new" BasicID 的属性数。需要计算 MatchStrength
INNER JOIN
- 在 ParameterIDs 和 ValueIDs 上加入 "new" 与现有连接的连接
MatchStrength
- 计算每个 NC.BasicID、C.BasicID 组的 匹配 ParameterId
和 ValueID
组合,然后除以 ParamCount
得到匹配的百分比。
参考文献:
注意: 大型数据集的性能尚未经过测试,但您可能需要以下索引:{ parameterID, valueID }, { BasicID }
查询变体
如果您想 return 区分匹配的 BasicID 和 MatchStrength(无参数 ID),请使用以下内容:
SELECT DISTINCT NewBasicID, BasicID, MatchStrength
FROM
( SELECT NC.BasicID AS NewBasicID, C.BasicID, C.ParameterId, C.ValueId,
CONVERT( DECIMAL( 5, 0 ), COUNT( C.ParameterId ) OVER( PARTITION BY NC.BasicID, C.BasicID )) / ParamCount * 100 AS MatchStrength
FROM
( SELECT *, COUNT( ParameterId ) OVER( PARTITION BY BasicID ) AS ParamCount
FROM #NewConnection ) AS NC
INNER JOIN #Connection AS C
ON NC.ParameterId = C.ParameterId AND C.ValueId = NC.ValueId ) AS Matches
ORDER BY NewBasicID, MatchStrength DESC, BasicID
我需要在 SQL Server 2016 中找到类似的记录,如果我能根据它们的匹配程度对结果进行排序,那就太好了。 类似的匹配条件是 2 个细节 tables.
我的table结构是:
//Basic:
Id Title
1 Title 1
2 Title 2
3 Title 3
4 Title 4
5 Title 5
//Parameters:
Id Title
1 Param 1
2 Param 2
3 Param 3
4 Param 4
5 Param 5
//Values:
Id Value
1 Val 1
2 Val 2
3 Val 3
4 Val 4
5 Val 5
与连接tables:
BasicId ParameterId ValueId
1 1 2
1 3 1
1 4 5
2 1 1
2 2 4
2 3 2
3 1 2
3 3 1
3 4 4
4 1 2
4 4 2
4 5 2
5 1 1
5 2 5
5 3 3
在我的程序中的某个时刻,我使用参数和值创建了新的基本行(在内存中)。现在我需要知道:
- 数据库中是否有完全匹配相同参数和值的记录。
- 相似记录按匹配的参数和值的数量排序。
对于第一点,我是这样做的: 如果所有参数和值匹配,则 2 行相等。 现在我用所有参数和值的 ID 计算字符串并将其添加到 Basic table.
基本变为:
Id Title EqualString (this comes from connection table)
1 Title 1 1:2;3:1;4:5
2 Title 2 1:1;2:4;3:2
3 Title 3 1:2;3:1;4:4
4 Title 4 1:2;4:2;5:2
5 Title 5 1:1;2:5;3:3
效果很好,因为顺序是由 ParameterId ASC 定义的,而且我在 EqualString 列上有索引。在这一点上我应该说,我的基本 table 有大约 500 万条记录并且还在增长。
但是对于第二个问题,我不知道如何解决这种问题。
例如:
Input Title X1 1:1;2:4;3:2 100% Title 2
33% Title 5
Input Title X2 1:1;2:4;3:1 66% Title 2
33% Title 5
Input Title X3 1:2;3:1;5:5 66% Title 1
66% Title 3
Input Title X4 1:2;3:1;5:3 66% Title 3
33% Title 5
我使用 SQL Server 2016 并且可以完全控制安装数据库的计算机。
大约有 100 个参数值要检查它们是否匹配(在上面的示例中只有 3 个 - 它们用 ; 分隔)
我认为全文搜索不是答案(或者也许是),因为我需要 2 个逗号之间的精确匹配(例如 2:5)。
或者我应该采用完全不同的方法而不计算 EqualString(在插入 时很少)。
用例:
我正在构建销售动态产品的网页。这意味着,该用户在购买前对其进行配置。
例如:设置高度、宽度、颜色,选择material ...
现在我需要知道这个产品是否已经存在(其他人选择完全相同的参数(宽度、高度、颜色)和值(100、120、绿色)或者这是全新的产品。
配置的参数在参数 table 中,值在值 table.
测试数据
这是从问题中逐字复制的:
CREATE TABLE #Connection( BasicId INT, ParameterId INT, ValueId INT )
INSERT INTO #Connection
VALUES
( 1, 1, 2 ), ( 1, 3, 1 ), ( 1, 4, 5 ),
( 2, 1, 1 ), ( 2, 2, 4 ), ( 2, 3, 2 ),
( 3, 1, 2 ), ( 3, 3, 1 ), ( 3, 4, 4 ),
( 4, 1, 2 ), ( 4, 4, 2 ), ( 4, 5, 2 ),
( 5, 1, 1 ), ( 5, 2, 5 ), ( 5, 3, 3 )
这是新产品的示例数据
CREATE TABLE #NewConnection( BasicId INT, ParameterId INT, ValueId INT )
INSERT INTO #NewConnection
VALUES
( 10, 1, 2 ), ( 10, 2, 2 ), ( 10, 3, 1 ),
( 11, 1, 1 ), ( 11, 2, 4 ), ( 11, 3, 2 ),
( 12, 1, 0 ), ( 12, 2, 5 ), ( 12, 3, 3 )
查询
SELECT NC.BasicID AS NewBasicID, C.BasicID, C.ParameterId, C.ValueId,
CONVERT( DECIMAL( 5, 0 ), COUNT( C.ParameterId ) OVER( PARTITION BY NC.BasicID, C.BasicID )) / ParamCount * 100 AS MatchStrength
FROM
( SELECT *, COUNT( ParameterId ) OVER( PARTITION BY BasicID ) AS ParamCount
FROM #NewConnection ) AS NC
INNER JOIN #Connection AS C
ON NC.ParameterId = C.ParameterId AND C.ValueId = NC.ValueId
ORDER BY NewBasicID, MatchStrength DESC, C.BasicID, C.ParameterId
工作原理
#NewConnection
- 包含需要根据现有#Connection
table 检查的 "New Connection" 数据
ParamCount
- 计算每个 "new" BasicID 的属性数。需要计算MatchStrength
INNER JOIN
- 在 ParameterIDs 和 ValueIDs 上加入 "new" 与现有连接的连接
MatchStrength
- 计算每个 NC.BasicID、C.BasicID 组的 匹配ParameterId
和ValueID
组合,然后除以ParamCount
得到匹配的百分比。
参考文献:
注意: 大型数据集的性能尚未经过测试,但您可能需要以下索引:{ parameterID, valueID }, { BasicID }
查询变体
如果您想 return 区分匹配的 BasicID 和 MatchStrength(无参数 ID),请使用以下内容:
SELECT DISTINCT NewBasicID, BasicID, MatchStrength
FROM
( SELECT NC.BasicID AS NewBasicID, C.BasicID, C.ParameterId, C.ValueId,
CONVERT( DECIMAL( 5, 0 ), COUNT( C.ParameterId ) OVER( PARTITION BY NC.BasicID, C.BasicID )) / ParamCount * 100 AS MatchStrength
FROM
( SELECT *, COUNT( ParameterId ) OVER( PARTITION BY BasicID ) AS ParamCount
FROM #NewConnection ) AS NC
INNER JOIN #Connection AS C
ON NC.ParameterId = C.ParameterId AND C.ValueId = NC.ValueId ) AS Matches
ORDER BY NewBasicID, MatchStrength DESC, BasicID