Sql 使用LIKE运算符或更好的方法连接两个表的最佳实践
我有两个表必须在数据仓库中每天处理一次 消息表 Id整数主键 消息varcharmax 例如:Sql 使用LIKE运算符或更好的方法连接两个表的最佳实践,sql,sql-server,join,sql-like,data-warehouse,Sql,Sql Server,Join,Sql Like,Data Warehouse,我有两个表必须在数据仓库中每天处理一次 消息表 Id整数主键 消息varcharmax 例如: Id | Message 1 | Hi! This is the first message. 2 | the last message. PartId | Message 1 | This 2 | message, first 3 | last 可分享 部分整数主键 单词varchar100 例如: Id | Message 1 | Hi! This
Id | Message
1 | Hi! This is the first message.
2 | the last message.
PartId | Message
1 | This
2 | message, first
3 | last
可分享
部分整数主键
单词varchar100
例如:
Id | Message
1 | Hi! This is the first message.
2 | the last message.
PartId | Message
1 | This
2 | message, first
3 | last
表1包含要与表2进行比较的消息,以便了解每条消息属于哪些部分
所以上面的例子应该像这样返回
Id | MessageId | PartId
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
INSERT INTO ResultTable(MessageId, PartId)
SELECT MessageTable.Id as MessageId, PartTable.Id as PartID
FROM MessageTable m, PartTable p
WHERE
(SELECT COUNT(VALUE) FROM STRING_SPLIT(p.Word, ',') WHERE CHARINDEX(CONCAT(' ', VALUE, ' '), m.Message) > 0) = (SELECT COUNT(VALUE) FROM STRING_SPLIT(p.Word, ','))
因为messageid 1包含此关键字以及message和first,所以它可以是0和1的一部分。
当部件中的关键字用逗号分隔时,所有关键字都需要在消息中找到,而不考虑顺序
我大致为这个过程创建的存储过程是这样的
Id | MessageId | PartId
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
INSERT INTO ResultTable(MessageId, PartId)
SELECT MessageTable.Id as MessageId, PartTable.Id as PartID
FROM MessageTable m, PartTable p
WHERE
(SELECT COUNT(VALUE) FROM STRING_SPLIT(p.Word, ',') WHERE CHARINDEX(CONCAT(' ', VALUE, ' '), m.Message) > 0) = (SELECT COUNT(VALUE) FROM STRING_SPLIT(p.Word, ','))
尽管我还没有完全确认,但这个SQL语句似乎仍然有效。但这看起来不是一个好的做法
我是否应该尝试在PartTable上使用更多的关系方法,如下所示?然后,应该在消息中找到一个部件的所有单词行,以确定该消息属于该部件
Id | PartId | Word
1 | 1 | This
2 | 2 | message
3 | 2 | last
我可以在PartTable上使用字符串_SPLIT创建此表,或者可以重构PartTable。但我看不到将此表与MessageTable连接起来的方法。我还希望MessageTable中会有很多行
有人能帮我吗
谢谢,嗯。您可以组合所有部分和消息,并将部分拆分为单词。where子句可用于筛选,因此只包含匹配项。最终聚合和计数返回所有单词匹配的消息/部分对:
select m.id, pt.partid
from message m cross join
parttable pt cross apply
string_split(pt.words, ',') s
where m.message like '%' + s.value + '%'
group by m.id, pt.partid
having count(*) = (select count(*)
from parttable pt2 cross apply
string_split(pt.words, ',') s
where pt2.partid = pt.partid
);
鉴于您的数据结构,这是不高效的,并且很难在SQL Server中进行优化
parttable的更好结构是对查询的改进:
select m.id, ptn.partid
from message m join
(select ptn.*, count(*) over (partition by partid) as cnt
from parttablenormalized ptn
) ptn
on m.message like '%' + ptn.word + '%'
group by m.id, pnt.partid, cnt
having count(*) = cnt;
但是,性能可能变化不大。您还需要对消息进行非规范化处理,以实现更快的查询。单词是否需要是单独的单词?也就是说,这是否是第一条消息匹配partId 2?@JamieF否,我希望每个单词都用空格隔开。这就是我使用CONCAT“”、VALUE“”的原因。您能为我提供一些示例来消除消息的恶意吗?MessageTable仅包含id和消息正文。我不知道如何去规范化消息。