Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用LIKE运算符或更好的方法连接两个表的最佳实践_Sql_Sql Server_Join_Sql Like_Data Warehouse - Fatal编程技术网

Sql 使用LIKE运算符或更好的方法连接两个表的最佳实践

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整数主键 消息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 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和消息正文。我不知道如何去规范化消息。