2009-04-14 21 views
16

Gần đây tôi đã làm việc trên một số chức năng tìm kiếm cơ sở dữ liệu và muốn nhận một số thông tin như các từ trung bình trên mỗi tài liệu (ví dụ: trường văn bản trong cơ sở dữ liệu). Điều duy nhất tôi đã tìm thấy cho đến nay (không xử lý ngôn ngữ được lựa chọn bên ngoài DB) là:Sử dụng SQL để xác định số liệu đếm từ của trường văn bản

SELECT AVG(LENGTH(content) - LENGTH(REPLACE(content, ' ', '')) + 1) 
FROM documents 

Điều này có vẻ hoạt động * nhưng bạn có đề xuất nào khác không? Tôi hiện đang sử dụng MySQL 4 (hy vọng sẽ chuyển sang phiên bản 5 cho ứng dụng này sớm), nhưng tôi cũng quan tâm đến các giải pháp chung.

Cảm ơn!

* Tôi có thể tưởng tượng rằng đây là một cách khá thô để xác định điều này vì nó không tính đến HTML trong nội dung và nội dung tương tự. Đó là OK cho dự án cụ thể này nhưng một lần nữa là có cách tốt hơn?

Cập nhật: Để xác định ý tôi là "tốt hơn": chính xác hơn, hoạt động hiệu quả hơn hoặc chính xác hơn (dễ bảo trì, thực hành tốt, v.v.). Đối với nội dung tôi có, truy vấn ở trên đủ nhanh và chính xác cho dự án này, nhưng tôi có thể cần một thứ tương tự trong tương lai (vì vậy tôi đã hỏi).

+0

Bạn cần xác định "tốt hơn" –

Trả lời

33

Khả năng xử lý văn bản của MySQL không đủ tốt cho những gì bạn muốn. Một hàm được lưu trữ là một tùy chọn, nhưng có thể sẽ chậm. Đặt cược tốt nhất của bạn để xử lý dữ liệu trong MySQL là thêm user defined function. Nếu bạn định tạo phiên bản MySQL mới hơn, bạn cũng có thể thêm native function.

Cách "chính xác" là xử lý dữ liệu bên ngoài DB vì DB là để lưu trữ, không xử lý và bất kỳ quá trình xử lý nặng nào có thể tải quá nhiều vào DBMS. Ngoài ra, việc tính số lượng từ bên ngoài MySQL giúp dễ dàng thay đổi định nghĩa của những gì được tính là một từ. Làm thế nào về việc lưu trữ số lượng từ trong DB và cập nhật nó khi một tài liệu được thay đổi?

Ví dụ lưu trữ chức năng:

DELIMITER $$ 
CREATE FUNCTION wordcount(str TEXT) 
     RETURNS INT 
     DETERMINISTIC 
     SQL SECURITY INVOKER 
     NO SQL 
    BEGIN 
    DECLARE wordCnt, idx, maxIdx INT DEFAULT 0; 
    DECLARE currChar, prevChar BOOL DEFAULT 0; 
    SET maxIdx=char_length(str); 
    WHILE idx < maxIdx DO 
     SET currChar=SUBSTRING(str, idx, 1) RLIKE '[[:alnum:]]'; 
     IF NOT prevChar AND currChar THEN 
      SET wordCnt=wordCnt+1; 
     END IF; 
     SET prevChar=currChar; 
     SET idx=idx+1; 
    END WHILE; 
    RETURN wordCnt; 
    END 
$$ 
DELIMITER ; 
1

này nhanh hơn một chút, mặc dù chỉ hơi thiếu chính xác. Tôi tìm thấy nó 4% ánh sáng trên số lượng, đó là OK cho "ước tính" kịch bản.

SELECT 
    ROUND ( 
     (
      CHAR_LENGTH(content) - CHAR_LENGTH(REPLACE (content, " ", "")) 
     ) 
     /CHAR_LENGTH(" ")   
    ) AS count  
FROM documents 
Các vấn đề liên quan