【问题标题】:How to count words in specific column against matching words in another table如何计算特定列中的单词与另一个表中的匹配单词
【发布时间】:2014-12-28 20:05:54
【问题描述】:

我希望能够:

  • Table1 中的 column1 中提取特定单词 - 但仅从名为 wordTable2 中匹配的单词/em>,
  • 对已找到的单词数进行(n 个)计数,然后
  • 将此信息放入具有如下格式的永久表中:

决赛

Word    | Count
--------+------
Test    |     7
Blue    |     5
Have    |     2

目前我已经尝试过:

INSERT INTO final (word, count) 
SELECT
  extext
  , SUM(dbo.WordRepeatedNumTimes(extext, 'test')) AS Count
FROM [dbo].[TestSite_Info], [dbo].[table_words]
WHERE [dbo].[TestSite_Info].ExText = [dbo].[table_words].Words
GROUP BY ExText;

函数dbo.WordRepeatedNumTimes是:

ALTER function [dbo].[WordRepeatedNumTimes]
(@SourceString varchar(8000),@TargetWord varchar(8000))
RETURNS int
AS
BEGIN
DECLARE @NumTimesRepeated int
,@CurrentStringPosition int
,@LengthOfString int
,@PatternStartsAtPosition int
,@LengthOfTargetWord int
,@NewSourceString varchar(8000)

SET @LengthOfTargetWord = len(@TargetWord)
SET @LengthOfString = len(@SourceString)
SET @NumTimesRepeated = 0
SET @CurrentStringPosition = 0
SET @PatternStartsAtPosition = 0
SET @NewSourceString = @SourceString

WHILE len(@NewSourceString) >= @LengthOfTargetWord
  BEGIN
    SET @PatternStartsAtPosition = CHARINDEX (@TargetWord,@NewSourceString)
    IF @PatternStartsAtPosition <> 0
    BEGIN
      SET @NumTimesRepeated = @NumTimesRepeated + 1
      SET @CurrentStringPosition = @CurrentStringPosition + @PatternStartsAtPosition + 
        @LengthOfTargetWord
      SET @NewSourceString = substring(@NewSourceString, @PatternStartsAtPosition + 
        @LengthOfTargetWord, @LengthOfString)
    END
    ELSE
    BEGIN
      SET @NewSourceString = ''
    END
  END
RETURN @NumTimesRepeated
END

当我运行上面的INSERT 语句时,没有插入任何记录。

在表 TestSite_Info 中有一个名为 Extext 的列。在此列中,有随机文本 - 其中一个词是“测试”。
在另一个名为 Table_Words 的表中,我有一个名为 Words 的列,其中一个词是“测试”。所以理论上,由于单词是匹配的,我会把它捡起来,放到表Final中,然后在单词旁边(在另一列中)计数该单词的次数已在 TestSite_Info.Extext 中找到。

Table_Words

id|word
--+----
1 |Test
2 |Onsite
3 |Here
4 |As

TestSite_Info

ExText
-------------------------------------------------
This is a test, onsite test , test test i am here

预期的决赛表已在顶部给出。

-- 更新

现在我已经运行了 Abecee 代码块,这实际上可以恢复计数列和与单词相关的 id。

结果如下:

id|total
--+----
169 |3
170 |0
171 |5
172 |7
173 |1
174 |3

取自以下文本,它是从中提取的:

测试测试,我去了,这是一个测试,我正在写垃圾你好 但我不在乎关心和关心似乎是你会看到出现的词 四次以及单词单词单词单词单词,但是一个.! 谁知道这里发生了什么。

如您所见,ID 172 的计数出现了 7 次(作为参考,请参阅下面的 ID 号与单词相关的内容)这是不正确的,它应该出现 6 次(它为某些原因)以及 ID 171,即 care 一词,出现 4 次,但计数显示为 5 次。任何想法为什么会这样? 此外,我真正追求的是一种方式,因为您已经非常友好地完成了显示 ID 和计数的表格,但也在决赛桌中显示了与之相关的单词,所以我不必通过 ID 链接回来表以查看实际单词是什么。

Word|id
--+----
 as   |174
here  |173
word  |172
care  |171
hello |170
test  |169

【问题讨论】:

  • 到目前为止你尝试过什么?请考虑提供SQL Fiddle 与测试数据和您的 SQL 语句,它不能完全提供预期的结果。
  • 使用示例数据和所需结果编辑您的问题。
  • 您使用的是哪个版本的 SQL Server? - 是的:引用的文章实际上可能是相关的。对不起。
  • 感谢 Abecee 的帮助。我实际上有两个实例。如果我们可以让它在 SQL 2008 R2 上运行那就太好了,SQL Serv 2012 Standard 也是如此。
  • 嗨,Abecee,绝对辉煌,它就在附近。我已经运行了您的以下声明,但仍有一些事情没有加起来。我现在将更新的信息放入问题字段

标签: sql sql-server tsql count


【解决方案1】:

您可以按照更新的方式工作

WITH
Detail AS (
  SELECT
    W.id
    , W.word
    , T.extext
    , (LEN(REPLACE(T.extext, ' ', '  ')) + 2
      - LEN(REPLACE(' '
                    + UPPER(REPLACE(REPLACE(REPLACE(REPLACE(T.extext, ' ', '  '), ':', ' '), '.', ' '), ',', ' '))
                    + ' ', ' ' + UPPER(W.word) + ' ', '')) - 1
      ) / (LEN(W.word) + 2) count
  FROM Table_Words W
  JOIN TestSite_Info T
    ON CHARINDEX(UPPER(W.word), UPPER(T.extext)) > 0
)
INSERT INTO Result
SELECT
  id
  , SUM(count) total
FROM Detail
GROUP BY id
;

(忘记计算前面和末尾的空格,错过了一个符号更改,并且混淆了被空格包围的单词的长度。抱歉。感谢您的测试比我原来做的更彻底!)
在 SQL Server 2008 上测试:Updated SQL Fiddle 和 2012:Updated SQL Fiddle
还有with your test case

它:

  • 是纯 SQL(不需要 UDF),
  • 有一些调整的空间:
    • 存储单词全部小写/全部大写,除非大小写重要(这需要调整建议的解决方案。)
    • 存储要检查的字符串并删除所有标点符号。

如果需要更多详细信息,请发表评论。

【讨论】:

  • Abecee 我刚刚为您创建的脚本结果的原始问题添加了更多细节。它快到了,但还有一点点偏离
  • 快速检查基本上证实了你的发现。对不起。需要仔细看看。 - 我猜,Oracle 是没有选择的? ;-)
  • 感谢 Abecee 不,它必须在 SQL 中;)
  • 嗨,Abecee,你的结局好吗?
  • 嗨,达里斯。抱歉 - 目前无法真正处理它。
【解决方案2】:

据我所知,这可能会起作用。但是,如果您发布架构,事情会更清楚

create table final(
  word varchar(100),
  count integer
);

insert into final (word, count) 
select column1, count(*)
from table1, table2
where table1.column1 = table2.words
group by column1;

【讨论】:

  • @darrisford:您实际上应该更新您的问题,以便包括与您的问题相关的所有方面。
  • @darrisford:引用的文章sqlmag.com/t-sql/counting-instances-word-record 很可能对您的问题的适用性有限。但是你可能想提供原始数据来证明我错了。
【解决方案3】:

感谢您的所有帮助。 此解决方案的最佳方法是:

有 详细信息 ( 选择 标识号 , W.字 , 文本 , (LEN(REPLACE(T.extext, ' ', ' ')) + 2 - LEN(替换('' + UPPER(REPLACE(REPLACE(REPLACE(REPLACE(T.extext, ' ', ' '), ':', ' '), '.', ' '), ',', ' ')) + ' ', ' ' + UPPER(W.word) + ' ', '')) - 1 ) / (LEN(W.word) + 2) 计数 FROM Table_Words W 加入 TestSite_Info T ON CHARINDEX(UPPER(W.word), UPPER(T.extext)) > 0 ) 插入结果 选择 ID , SUM(计数) 总计 从细节 按 ID 分组

【讨论】:

    【解决方案4】:

    重新阅读问题描述,提出的SELECT 似乎试图将完整的“exText”字符串与单个“单词”对齐/连接 - 但基于相等性。然后,它在SELECT 列表中有“exText”,而“Result”似乎在等待单个单词。 (不过,INSERT 不会失败,只要该字段不受外键约束的保护。但由于 WHERE/JOIN 不太可能让任何数据通过,这可能永远不会出现无论如何都是一个问题。)
    对于纯声明性方法的替代方法,您可能想尝试一下

    INSERT INTO final (word, count)
    SELECT
      word
      , SUM(dbo.WordRepeatedNumTimes(extext, word)) AS Count
    FROM [dbo].[TestSite_Info], [dbo].[table_words]
    WHERE  CHARINDEX(UPPER([dbo].[table_words].Word), UPPER([dbo].[TestSite_Info].ExText)) > 0
    GROUP BY word;
    

    您的“Table_Words”描述中有“Word” - 但在WHERE 条件中使用“[dbo].[table_words].Words”...

    【讨论】:

      猜你喜欢
      • 2022-06-21
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多