0

我有一张像这样的桌子:

Id     Word
---    ----
1      this
2      is
3      a
4      cat.
5      that
6      is
7      a
8      dog.
9      and
10     so
11     on

并且需要根据点字符为句号添加一个新列:

Id     Word     S#
---    ----     --
1      this     1
2      is       1
3      a        1
4      cat.     1
5      that     2
6      is       2
7      a        2
8      dog.     2
9      and      3
10     so       3
11     on       3

从性能方面来看,最好的解决方案是什么?

4

3 回答 3

2
select table.id, table.word, count(*) + 1 as serial_number
from table left join
( select id, word from table where word like '%.' ) Z 
on table.id > Z.id
group by table.id, table.word
于 2012-07-08T17:36:55.693 回答
1

您假设句子是由升序的 id 编号形成的。这真是个坏主意。

此查询应为您提供有关断句的信息。(用真实的表名替换“T”。)

SELECT
    Break1.Id as BreakId,
    COALESCE(MAX(Break2.Id), 0) as PreviousBreakId,
    COALESCE(COUNT(Break2.Id), 0) + 1 as BreakNumber
FROM
    (SELECT Id FROM T WHERE Word LIKE '%.') as Break1,
    (SELECT Id FROM T WHERE Word LIKE '%.') as Break2
WHERE Break2.Id < Break1.Id
GROUP BY Break1.Id

以下是在 UPDATE 中使用它的方法。

UPDATE T
SET SentenceNum = (
    SELECT B.BreakNumber
    FROM
        (
        SELECT
            Break1.Id as BreakId,
            COALESCE(MAX(Break2.Id), 0) as PreviousBreakId,
            COALESCE(COUNT(Break2.Id), 0) + 1 as BreakNumber
        FROM
            (SELECT Id FROM T WHERE Word LIKE '%.') as Break1,
            (SELECT Id FROM T WHERE Word LIKE '%.') as Break2
        WHERE
            Break2.Id < Break1.Id
        GROUP BY Break1.Id
        ) as B
    WHERE T.Id >= B.PreviousBreak AND T.Id < B.BreakId
)

我提供教育价值的查询,但我不能宽恕基于您的信息的方法。

编辑

我的原始版本的第一句话有问题,因为基本上逻辑会查找不存在的前句中断。@cravoori 的解决方案通过左连接来处理这个问题。这是一个与我自己的答案相同的工作版本,它返回完整的单词列表而不是中断。除了交叉连接和虚拟零行之外,本质上是相同的。

SELECT T.Id, MIN(T.Word) as Word, COUNT(Breaks.Id) as SentenceNumber
FROM T, (SELECT 0 as Id UNION ALL SELECT Id FROM T WHERE Word LIKE '%.') as Breaks
WHERE Breaks.Id < T.Id
GROUP BY T.Id;
于 2012-07-08T17:56:09.917 回答
0

检查此查询以获得所需的输出:

DECLARE  @Sentence TABLE(idn int identity,word varchar(50))
INSERT INTO @Sentence
VALUES('this'),('is'),('a'),('cat.'),('that'),('is'),('a'),('dog.'),('and'),('so'),('on.'),('I'),('love'),('india.')
--SELECT * FROM @Sentence 
DECLARE @seq int=1
;WITH CTE(idn,word,seq) AS(
SELECT idn,word,CASE WHEN word not like '%.' then @seq END from @Sentence where idn=1
union all
SELECT s.idn,s.word,CASE WHEN s.word like '%.' then c.seq+1  else c.seq END from @Sentence s inner join CTE c on s.idn-1=c.idn
)
,CTE1(idn,word,seq) As
(SELECT idn,word,CASE WHEN word like '%.' then seq-1 else seq end as seq from CTE)

SELECT * FROM CTE1
于 2012-07-09T09:55:05.227 回答