2012-07-10 45 views
7

Tôi có truy vấn sparql trả về các bản sao và tôi muốn nó xóa sạch chúng trên một trong các giá trị (subjectID). Không giống như DISTINCT mà dường như tìm một giá trị duy nhất cho sự kết hợp của các giá trị được chọn, thay vì chỉ một trong các tham số. Tôi thấy ai đó ở đây đề xuất nhóm theo, nhưng điều đó chỉ có thể áp dụng nếu tôi liệt kê tất cả các tham số sau nhóm (điểm cuối sparql của tôi phàn nàn, ví dụ: biến khóa không phải nhóm trong SELECT:? Occupation). Tôi đã thử chạy một lựa chọn nội bộ, nhưng nó dường như không hoạt động cho truy vấn cụ thể này. Vì vậy, có thể là một vấn đề với các truy vấn chính nó (các giá trị của các liveIn tùy chọn dường như gây ra bản sao)?Phím Sparql so với các giá trị khác nhau

Trong khi đủ hạnh phúc với các DB quan hệ sớm trong đường cong học tập với SPARQL, vì vậy hãy giải thích rõ ràng cho các trường hợp không được khởi xướng! :)

select distinct 
    ?subjectID ?englishName ?sex ?locatedIn15Name 
    ?dob ?dod ?dom ?bornLocationName ?occupation 
    where { 
     ?person a hc:Person ; 
     hc:englishName ?englishName ; 
     hc:sex ?sex; 
     hc:subjectID ?subjectID; 
     optional { ?person hc:livedIn11 ?livedIn11 . 
      ?livedIn11 hc:englishName ?lived11LocationName . 
      ?livedIn11 hc:locatedIn11 ?locatedIn11 . 
      ?locatedIn11 hc:englishName ?locatedIn11Name . 
      ?locatedIn11 hc:locatedIn15 ?locatedIn15 . 
?locatedIn15 hc:englishName ?locatedIn15Name . 
} . 
     optional {?person hc:born ?dob } . 
     optional {?person hc:dateOfDeath ?dod } . 
     optional {?person hc:dateOfMarriage ?dom } . 
     optional { ?person hc:bornIn ?bornIn . 
     ?bornIn hc:englishName ?bornLocationName . 
      ?bornIn hc:easting ?easting . 
      ?bornIn hc:northing ?northing } . 
     optional { ?person hc:occupation ?occupation } 
     FILTER regex(?englishName, "^FirstName LastName") 
     } 
    GROUP BY 
    ?subjectID ?englishName ?sex 
    ?locatedIn15Name ?dob ?dod ?dom 
    ?bornLocationName ?occupation 

Trả lời

12

Re được thông báo lỗi: biến

Non-nhóm chủ chốt trong CHỌN: nghề nghiệp

Bạn có thể tránh điều này bằng cách sử dụng các SAMPLE() tổng hợp - điều này sẽ cho phép bạn chỉ cần nhóm trên ?subjectID nhưng vẫn chọn giá trị cho các biến còn lại, miễn là bạn chỉ quan tâm đến việc nhận một giá trị cho các biến khác đó.

Dưới đây là một ví dụ đơn giản này:

SELECT ?subjectID (SAMPLE(?dob) AS ?dateOfBirth) 
WHERE 
{ 
    ?person a hc:Person ; 
      hc:subjectID ?subjectID . 
    OPTIONAL { ?person hc:born ?dob } 
} 
GROUP BY ?subjectID 
+0

+1 cho (IMHO) sử dụng SAMPLE không chính thống. –

+0

Cảm ơn Rob, đó là thực sự tiện dụng! Tôi đoán rằng đó là một số mẫu không xác định, do đó, để được sử dụng một cách thận trọng? :) – Nava

+0

PS Sẽ upvote một lần tôi kiếm được một chút danh tiếng hơn. – Nava

9

Điều đầu tiên cần lưu ý là không có những điều như một chìa khóa, thực sự, trong RDF/SPARQL. Bạn đang truy vấn một biểu đồ và ?subjectID chỉ đơn giản là có thể có một số kết hợp giá trị có thể cho các biến khác mà bạn đang chọn. Điều này là do hình dạng của biểu đồ bạn đang truy vấn: có thể là người của bạn có nhiều hơn một tên tiếng Anh, hoặc thực sự theo cách khác xung quanh: cùng một tên tiếng Anh có thể được chia sẻ bởi nhiều người.

Truy vấn SPARQL SELECT là một con thú lạ: nó truy vấn cấu trúc biểu đồ nhưng trình bày kết quả dưới dạng bảng phẳng (về mặt kỹ thuật, đó là chuỗi các kết hợp biến đổi, nhưng nó tương đương với cùng một giá trị). Sự trùng lặp xảy ra vì có thể tìm thấy các kết hợp giá trị khác nhau cho các biến của bạn bằng cách theo các đường dẫn khác nhau trong biểu đồ.

Thực tế là bạn nhận được giá trị trùng lặp cho ?subjectID trong kết quả của bạn do đó là không thể tránh khỏi, đơn giản vì đây là từ quan điểm của biểu đồ RDF, giải pháp duy nhất cho truy vấn của bạn. Bạn không thể lọc ra các kết quả mà không thực sự mất thông tin, vì vậy nói chung khó có thể cung cấp cho bạn giải pháp mà không biết chính xác hơn trong đó 'trùng lặp' bạn muốn hủy: bạn chỉ muốn một tên tiếng Anh cho mỗi chủ đề hoặc một ngày sinh có thể (mặc dù có thể có nhiều hơn một ngày trong dữ liệu của bạn)?

Tuy nhiên, đây là một số lời khuyên cho việc xử lý/khi xử lý kết quả như vậy dễ dàng hơn:

Trước hết, bạn có thể chọn để sử dụng một khoản ORDER BY trên biến ?subjectID của bạn. Điều này sẽ vẫn cung cấp cho bạn một số hàng có cùng giá trị cho ?subjectID, nhưng tất cả đều sẽ theo thứ tự, vì vậy bạn có thể xử lý kết quả của mình hiệu quả hơn.

Một giải pháp khác là chia truy vấn của bạn thành hai: thực hiện truy vấn đầu tiên chỉ chọn tất cả các đối tượng duy nhất (và có thể tất cả các giá trị khác mà bạn biết trước đó sẽ là duy nhất cho chủ đề), sau đó lặp lại kết quả và thực hiện truy vấn riêng để nhận các giá trị khác mà bạn quan tâm, cho từng giá trị SubjectID riêng lẻ. Giải pháp này nghe có vẻ như dị giáo (đặc biệt nếu bạn đến từ một nền SQL), nhưng nó thực sự có thể nhanh hơn và dễ dàng hơn là cố gắng làm mọi thứ trong một truy vấn lớn.

Một giải pháp khác là giải pháp được RobV đề xuất: sử dụng tổng hợp SAMPLE trên một biến cụ thể để chỉ chọn một giá trị duy nhất (ngẫu nhiên). Một biến thể trên đó là sử dụng tổng hợp GROUP_CONCAT, tạo ra một giá trị duy nhất bằng cách ghép tất cả các giá trị có thể vào một chuỗi đơn.

+0

Wow, cảm ơn, điều đó vô cùng hữu ích. Tôi đã học được rất nhiều đọc câu trả lời của bạn. Trong khi tôi chờ đợi, tôi thực sự tái cấu trúc một chút và chia truy vấn thành hai. Nó đi ngược lại ý thức của tôi về hiệu quả, nhưng nó là một giải pháp sạch sẽ và đơn giản. Tôi chưa bao giờ sử dụng 'GROUP_CONCAT' trong SQL, nhưng về cơ bản, điều này giải quyết được câu hỏi của tôi về việc làm gì với cấu trúc biểu đồ phẳng. Câu hỏi tiếp theo của tôi, đã làm trống trước rồi! (như với RobV, upvote để làm theo khi tôi đã kiếm được một chút danh tiếng hơn) – Nava

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