2016-05-26 23 views
6

Vì vậy, chúng tôi có this database chứa đầy một chuỗi các chuỗi, trong trường hợp này là tiêu đề bài đăng.Nhận các từ được sử dụng nhiều nhất từ ​​một cột chuỗi trong SQL

Những gì tôi muốn làm là:

  1. Chia chuỗi lên trong lời
  2. Đếm bao nhiêu lần lời xuất hiện trong chuỗi
  3. Hãy cho tôi đầu trang 50 từ
  4. Không có điều này thời gian chờ trong truy vấn data.se

Tôi đã thử sử dụng thông tin từ this SO question được điều chỉnh cho dữ liệu.se như sau:

select word, count(*) from (
select (case when instr(substr(p.Title, nums.n+1), ' ') then substr(p.Title, nums.n+1) 
      else substr(p.Title, nums.n+1, instr(substr(p.Title, nums.n+1), ' ') - 1) 
     end) as word 
from (select ' '||Title as string 
     from Posts p 
    )Posts cross join 
    (select 1 as n union all select 2 union all select 10 
    ) nums 
where substr(p.Title, nums.n, 1) = ' ' and substr(p.Title, nums.n, 1) <> ' ' 
) w 
group by word 
order by count(*) desc 

Thật không may, điều này mang lại cho tôi một loạt các lỗi:

'substr' không phải là một công nhận built-in tên hàm. Cú pháp không chính xác gần '|'. Cú pháp không chính xác gần 'nums'.

Vì vậy, cho một cột chuỗi trong SQL với số lượng văn bản thay đổi trong mỗi chuỗi, làm cách nào tôi có thể nhận danh sách các từ X được sử dụng thường xuyên nhất?

+0

liên quan, có thể trùng lặp: [Làm thế nào bạn có thể nhận được n từ phổ biến nhất trong một tập của nhiều hàng trả lại trong một truy vấn SQL Server?] (Http: //stackoverflow.com/q/3205696/1849664) – Undo

+2

Truy vấn đó đang sử dụng cú pháp SQLite cụ thể, trong khi bạn cần cú pháp SQL Server. – Blorgbeard

+0

Điểm thưởng nếu bạn viết truy vấn trong trình thám hiểm dữ liệu và có thể chạy nó mà không bị lỗi trên Stack Overflow bằng tiếng Bồ Đào Nha! Chúng tôi đưa ra điểm thưởng, phải không? – jmac

Trả lời

7

Như Blogbeard đã nói, truy vấn bạn cung cấp không hoạt động với SQL Server. Đây là một cách để đếm từ được sử dụng nhiều nhất. Điều này được dựa trên một hàm, DelimitedSplitN4K, được viết bởi Jeff Moden và được cải thiện bởi các thành viên của cộng đồng Trung tâm Máy chủ SQL.

ONLINE DEMO

WITH E1(N) AS (
    SELECT 1 FROM (VALUES 
     (1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
    ) t(N) 
), 
E2(N) AS (SELECT 1 FROM E1 a CROSS JOIN E1 b), 
E4(N) AS (SELECT 1 FROM E2 a CROSS JOIN E2 b) 
SELECT TOP 50 
    x.Item, 
    COUNT(*) 
FROM Posts p 
CROSS APPLY (
    SELECT 
     ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1), 
     Item  = LTRIM(RTRIM(SUBSTRING(p.Title, l.N1, l.L1))) 
     FROM (
      SELECT s.N1, 
       L1 = ISNULL(NULLIF(CHARINDEX(' ',p.Title,s.N1),0)-s.N1,4000) 
      FROM(
       SELECT 1 UNION ALL 
       SELECT t.N+1 
       FROM(
        SELECT TOP (ISNULL(DATALENGTH(p.Title)/2,0)) 
         ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
        FROM E4 
       ) t(N) 
       WHERE SUBSTRING(p.Title ,t.N,1) = ' ' 
      ) s(N1) 
     ) l(N1, L1) 
) x 
WHERE x.item <> '' 
GROUP BY x.Item 
ORDER BY COUNT(*) DESC 

Kể từ khi tạo ra các chức năng không được phép, tôi đã viết nó như vậy. Dưới đây là định nghĩa chức năng nếu bạn quan tâm:

CREATE FUNCTION [dbo].[DelimitedSplitN4K](
    @pString NVARCHAR(4000), 
    @pDelimiter NCHAR(1) 
) 
RETURNS TABLE WITH SCHEMABINDING AS 
RETURN 

WITH E1(N) AS (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
), 
E2(N) AS (SELECT 1 FROM E1 a, E1 b), 
E4(N) AS (SELECT 1 FROM E2 a, E2 b), 
cteTally(N) AS(
    SELECT TOP (ISNULL(DATALENGTH(@pString)/2,0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
), 
cteStart(N1) AS (
    SELECT 1 UNION ALL 
    SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter 
), 
cteLen(N1,L1) AS(
    SELECT s.N1, 
     ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,4000) 
    FROM cteStart s 
) 
SELECT 
    ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1), 
    Item  = SUBSTRING(@pString, l.N1, l.L1) 
FROM cteLen l 
; 

Và đây là cách bạn sẽ sử dụng nó:

SELECT TOP 50 
    x.Item, 
    COUNT(*) 
FROM Posts p 
CROSS APPLY dbo.DelimitedSplitN4K(p.Title, ' ') x 
WHERE LTRIM(RTRIM(x.Item)) <> '' 
GROUP BY x.Item 
ORDER BY COUNT(*) DESC 

Kết quả:

Item    
-------- ------- 
to  3812411 
in  3331522 
a  2543636 
How  1770915 
the  1534298 
with  1341632 
of  1297468 
and  1166664 
on  970554 
from  964449 
for  886007 
not  835979 
is  704724 
using 703007 
I  633838 
-  632441 
an  548450 
when  449169 
file  409717 
how  358745 
data  335271 
do  323854 
can  310298 
get  305922 
or  266317 
error 263563 
use  258408 
value 254392 
it  251254 
my  238902 
function 235832 
by  231025 
Android 228308 
as  216654 
array 209157 
working 207445 
does  207274 
Is  205613 
multiple 203336 
that  197826 
Why  196979 
into  196591 
after 192056 
string 189053 
PHP  187018 
one  182360 
class 179965 
if  179590 
text  174878 
table 169393 
1

giải pháp Query (Không Yêu cầu chức năng tách)

PostgreSQL

select word, count(*) from 
(
    -- get 1st words 
    select split_part(title, ' ', 1) as word 
    from posts 

    union all 

    -- get 2nd words 
    select split_part(title, ' ', 2) as word 
    from posts 

    union all 

    -- get 3rd words 
    select split_part(title, ' ', 3) as word 
    from posts 

    -- can do this as many times as the number of words in longest title 

) words 
where word is not null 
and word NOT IN ('', 'and', 'for', 'of', 'on') 
group by word 
order by count desc 
limit 50; 

cho một phiên bản ngắn gọn, xem: https://dba.stackexchange.com/a/82456/95929

Các vấn đề liên quan