SQL: количество проблемных слов с помощью len () - PullRequest
4 голосов
/ 11 августа 2011

Я пытаюсь посчитать слова текста, который написан в столбце таблицы.Поэтому я использую следующий запрос.

SELECT LEN(ExtractedText) - 
LEN(REPLACE(ExtractedText, ' ', '')) + 1 from EDDSDBO.Document where ID='100'.

Я получаю неправильный результат, который слишком велик.С другой стороны, если я копирую текст непосредственно в оператор, он работает, то есть

SELECT LEN('blablabla text') - LEN(REPLACE('blablabla text', ' ', '')) + 1.

Теперь тип данных nvarchar(max), так как текст очень длинный.Я уже пытался преобразовать столбец в text или ntext и применить datalength() вместо len().Тем не менее я получаю тот же результат, что он работает как строка, но не работает из таблицы.

Ответы [ 4 ]

2 голосов
/ 11 августа 2011

Вы считаете пробелы, а не слова.Это обычно дает приблизительный ответ.

например,

'  this     string    will    give an    incorrect      result   '

Попробуйте этот подход: http://www.sql -server-helper.com / functions / count-words.aspx

CREATE FUNCTION [dbo].[WordCount] ( @InputString VARCHAR(4000) ) 
RETURNS INT
AS
BEGIN

DECLARE @Index          INT
DECLARE @Char           CHAR(1)
DECLARE @PrevChar       CHAR(1)
DECLARE @WordCount      INT

SET @Index = 1
SET @WordCount = 0

WHILE @Index <= LEN(@InputString)
BEGIN
    SET @Char     = SUBSTRING(@InputString, @Index, 1)
    SET @PrevChar = CASE WHEN @Index = 1 THEN ' '
                         ELSE SUBSTRING(@InputString, @Index - 1, 1)
                    END

    IF @PrevChar = ' ' AND @Char != ' '
        SET @WordCount = @WordCount + 1

    SET @Index = @Index + 1
END

RETURN @WordCount

END
GO

использование

DECLARE @String VARCHAR(4000)
SET @String = 'Health Insurance is an insurance against expenses incurred through illness of the insured.'

SELECT [dbo].[WordCount] ( @String )
1 голос
/ 11 августа 2011

Замените пробелы на то, что никогда не встречается в вашем тексте, например '$!' или выберите другое значение. тогда замените все '$! 'и' $! ' без этого пути у вас никогда не будет больше 1 пробела после слова. Затем используйте свой текущий скрипт. Я определил слово как пробел, за которым следует не пробел.

Это пример

DECLARE @T TABLE(COL1 NVARCHAR(2000), ID INT)

INSERT @T VALUES('A B  C   D', 100)

SELECT LEN(C) - LEN(REPLACE(C,' ', '')) COUNT FROM (
SELECT REPLACE(REPLACE(REPLACE(' ' + COL1, ' ', ' $!'), '$! ',''), '$!', '') C
FROM @T ) A

Вот рекурсивное решение

DECLARE @T TABLE(COL1 NVARCHAR(2000), ID INT)

INSERT @T VALUES('A B  C   D', 100)
INSERT @T VALUES('have a nice day with 7 words', 100)

;WITH CTE AS
(
SELECT 1 words, col1 c, col1 FROM @t WHERE id = 100
UNION ALL
SELECT words +1, right(c, len(c) - patindex('% [^ ]%', c)), col1 FROM cte
WHERE patindex('% [^ ]%', c) > 0
)
SELECT words, col1 FROM cte WHERE patindex('% [^ ]%', c) = 0
1 голос
/ 11 августа 2011

Ведущие пробелы, конечные пробелы, два или более пробелов между соседними словами - это вероятные причины неверных результатов, которые вы получаете.

Функции LTRIM() и RTRIM() могут помочь вам устранитьпервые два вопроса.Что касается третьего, вы можете использовать REPLACE(ExtractedText, ' ', ' ') для замены двойных пробелов на одиночные, но я не уверен, что у вас нет тройных (в этом случае вам нужно будет повторить замену).


ОБНОВЛЕНИЕ

Вот UDF, который использует CTE и ранжирование для устранения лишних пробелов, а затем считает оставшиесявернуть количество в виде количества слов:

CREATE FUNCTION fnCountWords (@Str varchar(max))
RETURNS int
AS BEGIN
  DECLARE @xml xml, @res int;
  SET @Str = RTRIM(LTRIM(@Str));
  WITH split AS (
    SELECT
      idx = number,
      chr = SUBSTRING(@Str, number, 1)
    FROM master..spt_values
    WHERE type = 'P'
      AND number BETWEEN 1 AND LEN(@Str)
  ),
  ranked AS (
    SELECT
      idx,
      chr,
        rnk = idx - ROW_NUMBER() OVER (PARTITION BY chr ORDER BY idx)
      FROM split
  )
  SELECT @res = COUNT(DISTINCT rnk) + 1
  FROM ranked
  WHERE chr = ' ';
  RETURN @res;
END

С помощью этой функции ваш запрос будет выглядеть следующим образом:

SELECT fnCountWords(ExtractedText)
FROM EDDSDBO.Document
WHERE ID='100'

ОБНОВЛЕНИЕ 2

Функция использует одну из системных таблиц master..spt_values в качестве таблицы подсчета.Конкретное используемое подмножество содержит только значения от 0 до 2047. Это означает, что функция не будет работать правильно для вводов, длина которых превышает 2047 символов (после обрезания начального и конечного пробелов), как @ t-clausen.dk правильно отметил в своем комментарии.Поэтому следует использовать пользовательскую таблицу , если возможны более длинные входные строки.

0 голосов
/ 11 августа 2011

Вы должны объявить столбец, используя тип данных varchar, например:

create table emp(ename varchar(22));

insert into emp values('amit');

select ename,len(ename) from emp;

выход: 4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...