ויקינתונים:מדריך SPARQL

This page is a translated version of the page Wikidata:SPARQL tutorial and the translation is 64% complete.
Outdated translations are marked like this.

WDQS, שירות התשאול של ויקינתונים, הוא כלי רב עוצמה להפקת תובנות לפי התוכן של ויקינתונים. המדריך הזה ילמד אותך איך להשתמש בו. ר׳ גם את המדריך האינטראקטיבי של ויקימדיה ישראל.

לפני שנכתוב שאילתת SPARQL משלך, כדאי להסתכל על {{Item documentation}} או על כל תבנית שאילתת SPARQL כללית אחרת ולראות אם השאילתה הנחוצה לך כבר שם.

לפני שנתחיל

למרות שהמדריך הזה נראה ארוך ומאיים, אין סיבה לחשוש! למידת היסודות של SPARQL תיקח אותך הרחק - אפילו אם בחרת להפסיק לקרוא אחרי #השאילת הראשונה שלנו, כבר תתגבש אצלך הבנה מספקת להרכבת מגוון רחב של שאילתות מעניינות. כל סעיף במדריך הזה יעשיר אותך בכתיבת שאילתות יותר ויותר מדויקות.

אם מעולם לא שמעת על ויקינתונים, SPARQL או WQDS לפני כן, הנה הסבר קצר של המונחים האלה:

יסודות SPARQL

שאלת SPARQL פשוטה נראית ככה:

SELECT ?a ?b ?c
WHERE
{
  x y ?a.
  m n ?b.
  ?b f ?c.
}

הפסוקית SELECT כוללת את המשתנים שנרצה להחזיר (משתנים מתחילים בסימן שאלה), והפסוקית WHERE מכילה מגבלות עליהם, בעיקר בצורת שלישיות. כל המידע בוויקינתונים (ומסדי נתוני ידע דומים) מאוחסן בצורת שלישיות, כשמריצים את השאילתה, שירות התשאול ינסה למלא את המשתנים בערכים בפועל כדי שהשלישיות המתקבלות תופענה במסד נתוני הידע ותוחזרנה תוצאה אחת לכל צירוף משתנים שנמצאו.

שלישייה יכולה להיות כמו משפט (לכן היא מסתיימת בנקודה) עם נושא (subject), נשוא (predicate) ועצם (object):

SELECT ?fruit
WHERE
{
  ?fruit hasColor yellow.
  ?fruit tastes sour.
}

התוצאות לשאילתה הזאת יכולות לכלול, למשל, „לימון”. בוויקינתונים, רוב המאפיינים הם מסוג „יש” (has), לכן השאילתה יכולה להיראות כך:

SELECT ?fruit
WHERE
{
  ?fruit color yellow.
  ?fruit taste sour.
}

שיפורש בצורה ‎„?fruit has color ‘yellow’” (not?fruit is the color of ‘yellow’”)‎ ובעברית: ל?פרי יש את הצבע ‚צהוב’” (לא?פרי הוא הצבע של ‚צהוב’”) - חשוב לזכור את זה לטובת צמדי מאפיינים מהצורה „הורה”/„צאצא”!.

עם זאת, זאת לא דוגמה טובה ל־WQDS. טעם הוא סובייקטיבי, לכן לוויקינתונים אין מאפיין לזה. במקום, אפשר לחשוב על יחסי הורה/צאצא, שהם בדרך כלל חד־משמעיים.

השאילתה הראשונה שלנו

נניח שנרצה להציג את כל הצאצאים של המלחין מתקופת הבארוק יוהאן סבסטיאן באך. באמצעות רכיבים מדומים כמו בשאילתות להלן, איך כדאי לכתוב את השאילתה הזאת?

אמור היה לצאת משהו כזה:

SELECT ?child
WHERE
{
  #  child "has parent" Bach (‏(ל)צאצא ''יש הורה'' באך)
  ?child parent Bach.
  # ‫(נא לשים לב: כל מה שנכתב אחרי ‚#’ נחשב הערה ו־WQDS יתעלם ממנו.)
}

או ככה,

SELECT ?child
WHERE
{
  # child "has parent" Bach (‏(ל)צאצא ''יש אבא'' באך) 
  ?child father Bach. 
}

או ככה,

SELECT ?child
WHERE
{
  #  Bach "has child" child (‏(ל)באך ''יש צאצא'' צאצא)
  Bach child ?child.
}

שתי השלישיות הראשונות טוענות של־‎?child חייב להיות הורה/אבא בשם Bach, השלישית טוענת של־Bach יש את הצאצא ‎?child. בואו נמשיך עם האפשרות השנייה כרגע.

אם כן, מה צריך לעשות כדי להפוך את זה לשאילתה תקפה של WQDS? בוויקינתונים פריטים ומאפיינים לא מזוהים בשם שמובן לבני אדם כמו „אבא” (מאפיין) או „באך” (פריט). (יש לכך סיבה טובה: „יוהאן סבסטיאן באך” הוא גם השם של צייר גרמני, ו„באך” יכול גם להיות שם משפחה, קהילה צרפתית, מכתש בכוכב חמה וכן הלאה). במקום, לפריטים ולמאפיינים בוויקינתונים מוקצים מזהים. כדי למצוא מזהה של פריט עלינו לחפש את הפריט ולהעתיק את מספר ה־Q של התוצאה שנשמעת כמו הפריט שאנחנו מחפשים (לפי התיאור למשל). כדי למצוא מזהה של מאפיין, נעשה את אותו הדבר, אך נחפש אחר „‪P:<ביטוי לחיפוש>‬” במקום רק „ביטוי לחיפוש”, מה שיגביל את החיפוש למאפיינים. כך נוכל למצוא שהמלחין המפורסם יוהאן סבסטיאן באך מיוצג על ידי Q1339, ושהמאפיין להקצאת הורה לפריט הוא P:P22.

ואחרון חביב, צריך לכלול קידומות. לשלישיות פשוטות של WQDS, יש להוסיף קידומת wd:‎ לפריטים, ולמאפיינים את wdt:‎. (אך זה חל רק על ערכים קבועים - משתנים לא מקבלים קידומת!)

אם נחבר הכול יחד, נגיע לשאילתת ה־WDQS הראויה הראשונה שלנו:

SELECT ?child
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
}
Try it!

נלחץ על הקישור „לנסות את זה”, לאחר מכן על „ביצוע שאילתה” בעמוד ה־WDQS. מה יוצא?

child
wd:Q57225
wd:Q76428

קצת מאכזב. רואים רק את המזהים. אפשר ללחוץ עליהם כדי לראות את העמוד שלהם בוויקינתונים (כולל תווית שבני אדם יכולים להבין), אבל אין דרך טובה יותר לראות את התוצאות?

נו, כמובן שיש! (שאלות רטוריות זה דבר נפלא, לא?) אם כוללים את מלל הקסם

SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }

איפשהו בתוך פסוקית ה־WHERE יש משתנים נוספים: לכל משתנה ‎?foo בשאילתה שלך יש עכשיו גם משתנה ‎?fooLabel, which שמכיל את תווית הפריט שמאחורי ‎?foo. אם נוסיף אותו לפסוקית ה־SELECT יופיע הפריט וגם התווית שלו:

SELECT ?child ?childLabel
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

כדאי לנסות להריץ את השאילתה הזאת - אמורים להופיע לא רק מספרי הפריטים אלא גם שמות הצאצאים השונים.

child childLabel
wd:Q57225 יוהאן כריסטוף פרידריך באך
wd:Q76428 קארל פיליפ עמנואל באך

השלמה אוטומטית

לא נראה שקל כל כך לזכור את מקטע הקוד הזה עם SERVICE, נכון? ולהשתמש בחיפוש כל פעם בזמן כתיבת השאילתה זה גם די מייגע. למרבה המזל, WDQS מציע לכך פתרון נהדר: autocompletion (השלמה אוטומטית). בעורך השאילתות query.wikidata.org אפשר ללחוץ על Ctrl+רווח (or Alt+אנטר או Ctrl+Alt+אנטר) בכל נקודה בשאילתה ולקבל הצעות לקוד שיכול להתאים, את ההצעה המתאימה ניתן לבחור עם מקשי החצים למעלה/למטה ואז על אנטר כדי לבחור אותה.

למשל, במקום לכתוב SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } כל פעם מחדש, אפשר פשוט להקליד SERV, ללחוץ על Ctrl+רווח, והתוצאה הראשונה תהיה כישוף שירות התווית המלא, מוכן לשימוש! עכשיו צריך רק ללחוץ על אנטר כדי לאשר אותו. (העיצוב יהיה מעט שונה אבל זה לא משנה.)

השלמה אוטומטית יכולה גם לחפש עבורך. אם הקלדת את אחת מהקידומות של ויקינתונים כגון wd:‎ או wdt:‎, ואז את הטקסט לאחר מכן, Ctrl+רווח תחפש את הטקסט הזה בוויקינתונים ותציע תוצאות. wd:‎ מחפשת אחר פריטים, wdt:‎ אחר מאפיינים. למשל, במקום לחפש את הפריטים עבור Johann Sebastian Bach (Q1339) וfather (P22), אפשר פשוט להקליד wd:Bach ו־wdt:fath ואז פשוט לבחור את הרשומה המתאימה מההשלמה האוטומטית. (עובד אפילו עם רווחים בטקסט, למשל: wd:Johann Sebastian Bach.)

תבניות שלישיות מתקדמות

אז עכשיו פגשנו את כל הצאצאים של יוהאן סבסטיאן באך - יותר נכון: את כל הפריטים שהאבא שלהם הוא יוהאן סבסטיאן באך. אך לבאך היו שתי נשים, לכן לפריטים האלה יש שתי אימהות שונות: מה אם אנחנו רוצים לראות רק את הצאצאים של יוהאן סבסטיאן באך עם אשתו הראשונה, מריה ברברה באך (Q57487)? כדאי לנסות לכתוב את זה בשאילתה, לפי המידע שיש לנו.

סיימנו? מצוין, נעבור לפתרון! הדרך הפשוטה ביותר לעשות זאת היא להוסיף שלישייה שניה עם המגבלה הזאת:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339.
  ?child wdt:P25 wd:Q57487.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

בעברית המשמעות היא:

לילד יש אבא יוהאן סבסטיאן באך.

לילד יש אימא מריה ברברה באך.

נשמע מוזר, לא? בשפה טבעית נוכל לקצר את זה לביטוי:

לילד יש אבא יוהאן סבסטיאן באך ואימא מריה ברברה באך.

למעשה, אפשר לבטא את אותו הקיצור גם ב־SPARQL: אם סוגרים את השלישייה בנקודה פסיק (;) במקום בנקודה, אפשר להוסיף עוד צמד נשוא-עצם. כך נוכל לקצר את השאילתה שלעיל לכדי:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

שמציגה את אותן תוצאות אך עם פחות חזרות בשאילתה.

עכשיו נניח, שמתוך התוצאות האלו, מעניינים אותנו רק הצאצאים שהיו גם מלחינים ופסנתרנים. המאפיינים והפריטים הרלוונטיים הם occupation (P106), composer (Q36834) וpianist (Q486748). עכשיו ננסה לשנות את השאילתה שלהלן כדי להוסיף לה את המגבלות האלה!

הינה הפתרון שלי:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834;
         wdt:P106 wd:Q486748.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

כאן נעשה שימוש בקיצור ; פעמיים נוספות כדי להוסיף את שני העיסוקים הנחוצים. אך כפי שניתן לשים לב, עדיין יש חזרתיות. זה כמו שנגיד:

לילד יש עיסוק מלחין ועיסוק פסנתרן.

מה שבדרך כלל נוכל לקצר לביטוי:

לילד יש עיסוק מלחין ופסנתרן.

ול־SPARQL יש תחביר גם לזה: ממש כמו ש־; מאפשר להוסיף צמד נשוא-עצם לשלישייה (תוך שימוש בנושא לשתי מטרות), , מאפשר לך להוסיף עצם נוסף לסוף שלישייה (תוך ניצול של הנושא והנשוא לשתי מטרות). כך, אפשר לקצר את השאילתה לכדי:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834,
                  wd:Q486748.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

כדאי לשים לב: אין משמעות להזחות ולרווחים נוספים - הם רק מקלים על הקריאה. אפשר גם לכתוב את זה ככה:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834, wd:Q486748.
  # שני העיסוקים באותה שורה
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

או, בצורה הפחות נוחה לקריאה:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
  wdt:P25 wd:Q57487;
  wdt:P106 wd:Q36834,
  wd:Q486748.
  # אין הזחה, מקשה על הבדלה בין ; לבין ,
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

למרבה המזל, העורך של WDQS מזיח את השורות עבורך אוטומטית, כך שזה בדרך כלל לא אמור להטריד אותך.

מצוין, נערוך סיכום ביניים. ראינו ששאילתות בנויות כמו טקסט. כל שלישייה על נושא נסגרת בנקודה. מספר נשואים על אותו הנושא מופרדים בנקודה פסיק, ומגוון עצמים לאותו הנושא והנשוא ניתן לכתוב עם פסיקים ביניהם.

SELECT ?s1 ?s2 ?s3
WHERE
{
  ?s1 p1 o1;
      p2 o2;
      p3 o31, o32, o33.
  ?s2 p4 o41, o42.
  ?s3 p5 o5;
      p6 o6.
}

עכשיו נציג קיצור נוסף ש־SPARQL מציע. כל עוד נוכל לזרום בצחוק על עוד תרחיש מומצא…

נניח שאנחנו לא באמת מעוניינים בילדים של באך. (טוב, אולי אותך זה כן מעניין!) אבל אנחנו מעוניינים בנכדים שלו. (לכאורה.) יש כאן סיבוך מסוים: נכד יכול להיות קשור לבאך דרך האימא או דרך האבא. אלו שני מאפיינים שונים, שזה מצב לא נוח. במקום, נהפוך את הזיקה: לנתונים יש גם מאפיין „צאצא”, P:P40, שמפנה מההורה לצאצא ללא תלות במגדר. עם המידע הזה, אפשר לכתוב שאילתה שמחזירה את הנכדים של באך?

הינה הפתרון שלי:

SELECT ?grandChild ?grandChildLabel
WHERE
{
  wd:Q1339 wdt:P40 ?child.
  ?child wdt:P40 ?grandChild.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

בשפה טבעית, המשמעות היא:

לבאך יש ילד ‎?child.

ל־‎?child יש ילד ?grandChild.

גם כאן, אני מציע לקצר את המשפט הזה ואז ארצה להראות איך SPARQL תומך בקיצור דומה. בדרך הזאת לא ממש אכפת לנו מהצאצא: אנחנו לא משתמשים במשתנה למעט כדי לדבר על הנכד. לכן עלינו לקצר את המשפט הזה לכדי:

לבאך יש איזשהו ילד שיש לו ילד ‎?grandChild.

במקום להגיד איזה ילד זה של באך, אנחנו פשוט מציינים „מישהו”: לא אכפת לנו מי הוא. אבל אפשר להתייחס אליהם בחזרה כיוון שאמרנו „איזשהו/מישהו ש”: בכך פתחנו בפסוקית זיקה, ובתוך פסוקית הזיקה הזאת נוכל לציין דברים על „איזשהו/מישהו” (למשל: ש„יש להם ילד ‎?grandChild”). למעשה, „איזשהו/מישהו” הוא משתנה, אך מיוחד שתקף רק בתוך פסוקית הזיקה הזאת וכזה שאנחנו לא פונים אליו במפורש (אנחנו מציינים ש„למישהו שהוא זה ועושה את זה”, לא „מישהו שהוא זה ומישהו שעושה את זה” - זה לא אותו „מישהו”).

ב־SPARQL אפשר לכתוב את זה בתור:

SELECT ?grandChild ?grandChildLabel
WHERE
{
  wd:Q1339 wdt:P40 [ wdt:P40 ?grandChild ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

אפשר להשתמש בצמד סוגריים מרובעים ([]) במקום משתנה, שמתנהג כמו משתנה אלמוני. בתוך הסוגריים, אפשר לציין צמדים של נשוא-עצם, בדיוק כמו אחרי ; שאחרי שלישייה רגילה, הנושא המרומז הוא במקרה הזה המשתנה האלמוני שהסוגריים האלה מייצגים. (לתשומת ליבך: כמו מיד אחרי code>;, אפשר להוסיף עוד צמדי נשוא-עצם עם יותר נקודות פסיקים או יותר עצמים לאותו הנשוא עם פסיקים.)

זה הכול על תבניות שלישיות! יש עוד מה לגלות על SPARQL, אך כיוון שאנחנו מתכננים לעזוב את החלקים ממנו שהם אנלוגיים לטובת שפה טבעית, ארצה לסכם את היחס הזה פעם נוספת:

שפה טבעית דוגמה SPARQL דוגמה
משפט יוליה אוהבת את רומיאו. תקופה יוליה אוהבת את רומיאו.
חיבור (פסוקית) רומיאו אוהב את יוליה וגם הורג את עצמו. נקודה פסיק רומיאו אוהב את יוליה; הורג את רומיאו.
חיבור (שם עצם) רומיאו הורג את טיבלט וגם את עצמו. פסיק רומיאו הורג את טיבלט, רומיאו.
פסוקית זיקה יוליה אוהבת מישהו אשר הורג את טיבלט. סוגריים מרובעים יוליה אוהבת את [ הורג את טיבלט ].

מופעים ומחלקות

לפני כן, ציינתי שרוב המאפיינים של ויקינתונים הם זיקה מסוג „יש” (has): יש צאצא, יש אבא, יש עיסוק. אבל לפעמים (למעשה, לעיתים קרובות), צריך גם לדבר על אופיו של משהו (is). אך זה מתחלק למעשה לשני סוגים של קשרים:

  • חלף עם הרוח הוא סרט.
  • סרט הוא יצירת אומנות.

חלף עם הרוח הוא סרט מסוים אחד. יש לו במאי מסוים (ויקטור פלמינג), אורך מסוים (238 דקות), רשימת שחקנים (קלארק גייבל, ויויאן לי…), ועוד.

סרט הוא עקרון כללי. לסרטים יכולים להיות במאים, אורכים ושחקנים, אבל לעקרון „סרט” כפי שהוא אין במאי, משך או ליהוק מסוים. ולמרות שסרט הוא יצירת אומנות, וליצירת אומנות בדרך כלל יש יוצר, לעקרון „סרט” לכשעצמו אין יוצר – רק למופעים מסוימים של העקרון הזה יש.

ההבדל הזה הוא הסיבה לכך שיש שני מאפיינים עבור „is” (תת־קבוצה של/מופע של) בוויקינתונים: instance of (P31) וsubclass of (P279). חלף עם הרוח הוא מופע מסוים של המחלקה „סרט”, המחלקה „סרט” היא תת־מחלקה (ליתר דיוק מחלקה, התמחות) של מחלקה כללית יותר בשם „יצירת אומנות”.

כדי לסייע להבין את ההבדלים, אפשר לנסות להשתמש בשני פעלים שונים: „תת־קבוצה” ו„מופע של”. אם „תת־קבוצה” מתאים (למשל: סרט הוא „תת־קבוצה של” יצירת אומנות), זה אומר שמדובר בתת־מחלקה. מומחיות של מחלקה רחבה יותר ויש להשתמש בsubclass of (P279). אם „תת־מחלקה של” לא מתאים (למשל: המשפט חלף עם הרוח הוא „מופע של” סרט אין בו היגיון), זה אומר שמדובר במופע מסוים ושצריך להשתמש בinstance of (P31).

אז מה זה אומר לגבינו בעת כתיבת שאילתות SPARQL? כשאנו רוצים לחפש אחר „כל יצירות האומנות”, לא מספיק לחפש את כל הפריטים שהם מופעים ישירים של „יצירת אומנות”:

SELECT ?work ?workLabel
WHERE
{
  ?work wdt:P31 wd:Q838948. # מופע של יצירת אומנות
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

בזמן תרגום המדריך (דצמבר 2023), השאילתה הזאת החזירה רק 31,308 תוצאות - כמובן שיש הרבה יותר יצירות אומנות מהכמות הזאת! הבעיה היא שהשאילתה מחמיצה פריטים כמו חלף עם הרוח, שזה מופע של „סרט” בלבד ולא של „יצירת אומנות”. „סרט” זאת תת־מחלקה של „יצירת אומנות” אבל אנחנו צריכים לדרוש מ־SPARQL לקחת את זה בחשבון בזמן החיפוש.

פתרון אחד לכך הוא התחביר [] שדיברנו עליו: חלף עם הרוח הוא מופע של איזושהי תת־מחלקה של „יצירת אומנות”. (לצורך התרגול, כדאי לנסות לכתוב את השאילתה הזאת!) אך גם בגישה הזאת עדיין יש בעיות:

  1. אנחנו לא כוללים עוד פריטים שהם מופעים ישירים של יצירת אומנות.
  2. אנחנו עדיין מחמיצים פריטים שהם מופעים של תת־מחלקה כלשהי של איזה תת־מחלקה אחרת של „יצירת אומנות” - למשל, שלגיה ושבעת הגמדים הוא סרט מונפש, שהוא סרט, שהוא יצירת אומנות. במקרה הזה אנחנו צריכים לעקוב אחר שתי קביעות מסוג „תת־מחלקה של” - אבל זה יכול להיות גם שלושה, ארבעה, חמישה ולמעשה כל מספר.

הפתרון: ‎?item wdt:P31/wdt:P279* ?class‎. המשמעות היא שיש „מופע של” אחד ואז מספר כלשהו של קביעות מסוג „תת־מחלקה של” בין הפריט ובין המחלקה.

SELECT ?work ?workLabel
WHERE
{
  ?work wdt:P31/wdt:P279* wd:Q838948. # מופע של תת־מחלקה כלשהי של יצירת אומנות
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

(לא מומלץ להריץ את השאילתה הזאת. WDQS יכול להתמודד איתה (ממש בקושי), אבל הדפדפן שלך עלול לקרוס בעת ניסיון להציג את התוצאות כי יש הרבה מהן.)

עכשיו יותר ברור איך לחפש אחר כל יצירות האומנות או כל הבניינים או כל היישובים לבני אדם: כישוף הקסם wdt:P31/wdt:P279*‎, יחד עם המחלקה המתאימה. לשם כך נעשה שימוש בעוד כמה יכולות SPARQL שעדיין לא הסברתי עליהן, אבל למען ההגינות, זה בערך השימוש הרלוונטי היחידי של היכולות האלה כך שאין צורך אמיתי להבין איך זה עובד כדי להשתמש ב־WDQS ביעילות. אם חשוב לך לדעת, אסביר זאת בקצרה אבל אפשר פשוט לדלג לסעיף הבא ולשנן או להעתיק ולהדביק את wdt:P31/wdt:P279*‎ מכאן בעת הצורך.

נתיבי מאפיינים

נתיבי מאפיינים הן דרך לכתוב נתיב של מאפיינים בין שני פריטים בצורה תמציתית. הנתיב הפשוט ביותר הוא מאפיין יחיד, שמתגבש לכדי שלישייה פשוטה:

?item wdt:P31 ?class.

אפשר להוסיף רכיבי נתיב עם לוכסן (/).

?item wdt:P31/wdt:P279/wdt:P279 ?class.

שקול לאחד מהבאים:

?item wdt:P31 ?temp1.
?temp1 wdt:P279 ?temp2.
?temp2 wdt:P279 ?class.
?item wdt:P31 [ wdt:P279 [ wdt:P279 ?class ] ].

תרגיל: נא לשכתב את שאילתת „הנכדים של באך” מקודם לשימוש בתחביר הזה.

כוכבית (*) אחרי רכיב נתיב משמעה „אפס או יותר מהרכיב הזה”.

?item wdt:P31/wdt:P279* ?class.
# means:
?item wdt:P31 ?class
# or
?item wdt:P31/wdt:P279 ?class
# or
?item wdt:P31/wdt:P279/wdt:P279 ?class
# or
?item wdt:P31/wdt:P279/wdt:P279/wdt:P279 ?class
# or ...

אם אין רכיבים אחרים בנתיב, המשמעות של ‎?a something* ?b היא ש־‎?b יכול גם פשוט ‎?a ישירות בלי רכיבים ביניהם כלל.

פלוס (+) דומה לכוכבית, אך המשמעות שלו היא „אחד או יותר מהרכיב הזה”. השאילתה הבאה מוצאת את כל יוצאי חלציו של באך:

SELECT ?descendant ?descendantLabel
WHERE
{
  wd:Q1339 wdt:P40+ ?descendant.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

אם היינו משתמשים כאן בכוכבית במקום בפלוס, תוצאות השאילתה היו כוללות את באך בכבודו ובעצמו.

סימן שאלה (?) דומה לכוכבית או פלוס אך המשמעות שלו היא „אפס או אחד מהרכיב הזה”.

אפשר להפריד רכיבי נתיב בקו אנכי (|) במקום לוכסן, המשמעות היא „או או/או ש… או ש…” (either-or): הנתיב יכול להשתמש בכל אחד מהמאפיינים האלה. (אך לא במשולב - מקטע נתיב „או או” תמיד תואם לנתיב באורך אחד.)

אפשר גם לקבץ רכיבים עם סוגריים (()), ולשלב בחופשיות את כל רכיבי התחביר האלה (/|*+?). המשמעות היא שדרש נוספת למצוא את כל יוצאי חלציו של באך היא:

SELECT ?descendant ?descendantLabel
WHERE
{
  ?descendant (wdt:P22|wdt:P25)+ wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

במקום להשתמש במאפיין „צאצא” כדי לעבור מבאך לדורות המאוחרים, אנו משתמש במאפיינים „אבא” ו„אימא” כדי לעבור מהדורות המאוחרים לבאך. הנתיב יכול לכלול שתי אימהות ואבא אחד או ארבע אבות או אבא-אימא-אימא-אבא או כל שילוב אחר. (למרות, שבאך כמובן לא יכול להיות אימא של מישהו, לכן הרכיב האחרון תמיד יהיה אבא.)

מבחינים

(נפתח בחדשות הטובות: הפרק הזה לא מציג תחביר נוסף ב־SPARQL - היאח! אפשר לקחת הפסקה קצרה ולהירגע, זה אמור להיות קלי קלות. לא?)

עד כה דיברנו רק על קביעות פשוטות: נושא, מאפיין, עצם. אך הקביעות של ויקינתונים הן הרבה מעבר לזה: יכולים להיות להם גם מבחינים והפניות למקורות. למשל, למונה ליזה (Q12418) יש שלוש קביעות מסוג made from material (P186):

  1. oil paint (Q296955), החומר העיקרי,
  2. poplar wood (Q291034), עם המבחין applies to part (P518)painting support (Q861259) – זה החומר שעליו צוירה המונה ליזה, וגם
  3. wood (Q287), עם המבחינים applies to part (P518)stretcher (Q1737943) וstart time (P580) 1951 – זה החלק שנוסף לתמונה בשלב מאוחר יותר.

נניח שאנחנו רוצים למצוא את כל הציבורים עם משטח הציור שלהם, כלומר, קביעות made from material (P186) עם המבחין applies to part (P518)painting support (Q861259). איך עושים את זה? זה יותר מידע ממה שאפשר להציג בשלישייה אחת.

התשובה היא: עוד שלישיות! (כלל אצבע: הפתרון של ויקינתונים כמעט לכל דבר הוא „עוד פריטים”, והכלל התואם ב־WDQS הוא „עוד שלישיות”. הפניות למקורות, דיוק עשרוני, ערכים עם יחידות, נקודות ציון גאוגרפיות וכו׳, על כל אלה שאנחנו מדלגים עליהם כאן, עובדים כך גם כן.) עד כה, השתמשנו בקידומת wdt:‎ לשלישיית הקביעות שלנו, שמפנה ישירות לעצם הקביעה. אך יש גם קידומת נוספת p:‎, שמצביעה לא לעצם אלא לצומת קביעה. הצומת הזה הוא הנושא של שלישיות אחרות: הקידומת ps:‎ (ראשי תיבות של property statement - צומת קביעה) למבחינים ו־prov:wasDerivedFrom מפנה לצמתי הפניה למקורות (אנחנו נתעלם מזה כרגע).

זה היה המון טקסט מופשט. הנה דוגמה מוחשית למונה ליזה:

wd:Q12418 p:P186 ?statement1.    # Mona Lisa: material used: ?statement1
?statement1 ps:P186 wd:Q296955.  # value: oil paint

wd:Q12418 p:P186 ?statement2.    # Mona Lisa: material used: ?statement2
?statement2 ps:P186 wd:Q291034.  # value: poplar wood
?statement2 pq:P518 wd:Q861259.  # qualifier: applies to part: painting surface

wd:Q12418 p:P186 ?statement3.    # Mona Lisa: material used: ?statement3
?statement3 ps:P186 wd:Q287.     # value: wood
?statement3 pq:P518 wd:Q1737943. # qualifier: applies to part: stretcher bar
?statement3 pq:P580 1951.        # qualifier: start time: 1951 (pseudo-syntax)

נוכל לקצר את זה משמעותית עם התחביר [] שיחליף את משתני ‎?statement:

wd:Q12418 p:P186 [ ps:P186 wd:Q296955 ].

wd:Q12418 p:P186 [
            ps:P186 wd:Q291034;
            pq:P518 wd:Q861259
          ].

wd:Q12418 p:P186 [
            ps:P186 wd:Q287;
            pq:P518 wd:Q1737943;
            pq:P580 1951
          ].

ננסה להשתמש בידע הזה כדי לכתוב שאילתה לכל הציורים עם משטח הציור שלהם?

הינה הפתרון שלי:

SELECT ?painting ?paintingLabel ?material ?materialLabel
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

קודם, נגביל את ‎?painting לכל המופעים של painting (Q3305213) או תת־מחלקה שלו. לאחר מכן, נחלץ את החומר מצומת הקביעה p:P186 שיגביל את הקביעות לאלו שיש להן את המבחין applies to part (P518)painting support (Q861259).

ORDER ו־LIMIT (סידור והגבלה)

אנו חוזרים לתוכנית המקורית שלנו עם עוד יכולות של SPARQL.

עד עכשיו, נתקלנו בשאילתות שבהן היינו מעוניינים בכל התוצאות. בקשה יחסית נפוצה היא שרק חלק מהתוצאות נחוצות: בדרך כלל לקיצון מסוים - הוותיקות ביותר, הצעירות ביותר, הקדומות ביותר, העדכניות ביותר, עם כמות האוכלוסיה הגדולה ביותר, נקודת ההתכה הנמוכה ביותר, הכי הרבה ילדים, הכי הרבה חומרים לייצור וכן הלאה. הגורם המשותף כאן הוא שהתוצאות מדורגות באופן כלשהו, ואז אכפת לנו מכמות מסוימת של כמה תוצאות ראשונות בלבד (אלו עם הדירוג הטוב ביותר).

השליטה הזאת מתאפשרת באמצעות שתי פסוקיות שמצטרפות למקטע WHERE {}‎ (אחרי הסוגריים, לא בתוכם!): ORDER BY ו־LIMIT.

‪ORDER BY משהו‬ מסדר את התוצאות לפי משהו. משהו יכול להיות כל ביטוי שהוא – לבינתיים, הביטוי היחידי שאנחנו מכירים הם משתנים פשוטים (‎?something‎), אך בהמשך נראה סוגים אחרים. אפשר לעטוף את הביטוי הזה ב־ASC()‎ או ב־DESC()‎ כדי לציין את כיוון הסידור (ascending או descending - עולה או יורד בהתאמה). (כשלא מציינים אף אחד מהם, ברירת המחדל היא סדר עולה, לכן ‪ASC(משהו)‬ שקול לחלוטין לביטוי משהו כפי שהוא.)

‪LIMIT כמות‬ חותכת את רשימת התוצאות לכמות תוצאות, כאשר כמות הוא כל מספר טבעי שהוא. למשל, LIMIT 10 מגביל את השאילתה ל־10 תוצאות. LIMIT 1 מחזיר תוצאה אחת בלבד.

(אפשר גם להשתמש ב־LIMIT בלי ORDER BY. במקרה שכזה, התוצאות לא תסודרנה כך שאין שום ערובה לתוצאות שתתקבלנה. שזה בסדר אם במקרה ברור לך שיש כמות מסוימת של תוצאות, או שפשוט מעניין אותך להציג תוצאות כלשהן אבל לא אכפת לך איזה בדיוק. בכל מקרה, הוספת LIMIT יכולה להאיץ את השאילתה משמעותית, מאחר ש־WDQS יכול לעצור את החיפוש ברגע שנמצאו מספיק תוצאות למלא את הכמות.)

זמן לתרגל! נא לנסות לכתוב שאילתה שמחזירה את עשר המדינות המאוכלסות ביותר. (מדינה זה sovereign state (Q3624078), ומאפיין האוכלוסיה הוא P:P1082.) אפשר להתחיל על ידי חיפוש אחר מדינות עם האוכלוסיה שלהן, ואז להוסיף את הפסוקיות ORDER BY ו־LIMIT.

הינה הפתרון שלי:

SELECT ?country ?countryLabel ?population
WHERE
{
  ?country wdt:P31/wdt:P279* wd:Q3624078;
           wdt:P1082 ?population.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 10
Try it!

נא לשים לב שאם רצינו את המדינות המאוכלסות ביותר, צריך לסדר לפי אוכלוסיה בסדר יורד, כך שהתוצאות הראשונות תהיינה אלו עם הערכים הגדולים ביותר.

תרגול

כיסינו הרבה יסודות עד כה - לדעתי הגיע הזמן לקצת תרגולים. (אפשר לדלג על החלק הזה אם אין לך פנאי.)

ספרים של ארתור קונאן דויל

נא לכתוב שאילתה שמחזירה את כל הספרים של סיר ארתור קונאן דויל.

יסודות כימיים

נא לכתוב שאילתה שמחזירה את כל היסודות הכימיים עם הסימול והמספר האטומי שלהם בסדר עולה לפי המספר האטומי.

נחלים שזורמים לתוך נהר המיסיסיפי

נא לכתוב שאילתה שמחזירה את כל הנחלים שזורמים ישירות לנהר המסיסיפי. (האתגר העיקרי פה הוא למצוא את המאפיין הנכון…)

נחלים שזורמים לתוך נהר המיסיסיפי 2

נא לכתוב שאילתה שמחזירה את כל הנחלים שזורמים לתוך נהר המיסיסיפי, בישירות או בעקיפין.

OPTIONAL (רשות)

בתרגיל שלעיל, התבקשנו לבנות שאילתה שתמצא את כל הספרים מאת סר ארתור קונאן דויל:

SELECT ?book ?bookLabel
WHERE
{
  ?book wdt:P50 wd:Q35610.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

אבל זה קצת משעמם. יש המון נתונים מעניינים על ספרים, ואנחנו מציגים רק את התווית? בואו ננסה להכין שאילתה שכוללת גם את title (P1476), illustrator (P110), publisher (P123) וגם publication date (P577).

ניסיון ראשוני יכול להיראות כך:

SELECT <span lang="en" dir="ltr" class="mw-content-ltr">?book ?title ?illustratorLabel ?publisherLabel ?published</span>
WHERE
{
  ?book wdt:P50 wd:Q35610;
        wdt:P1476 ?title;
        wdt:P110 ?illustrator;
        wdt:P123 ?publisher;
        wdt:P577 ?published.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

יש להריץ את השאילתה הזאת. בזמן תרגום המסמך הזה, מוחזרות רק 21 תוצאות - ממש טיפה בים! למה זה ככה? לפני כן מצאנו למעלה ממאה ספרים!

הסיבה לכך היא שכדי לענות על השאילתה הזאת, על תוצאה אפשרית (ספר) לענות על כל השלישיות שהצבנו: זאת חייבת להיות כותרת, ומאייר, והוצאה לאור ותאריך פרסום. אם לספר יש כמה מהמאפיינים האלה אך לא את כולם הוא לא יענה לחיפוש. וזה לא מה שאנחנו רוצים במקרה הזה: אנחנו בעיקר רוצים רשימה של כל הספרים - אם יש מידע נוסף, נרצה לכלול אותו, אך לא נרצה שהוא יגביל את רשימת התוצאות שלנו.

הפתרון הוא לומר ל־WDQS שהשלישיות האלה הן בגדר רשות (optional):

SELECT <span lang="en" dir="ltr" class="mw-content-ltr">?book ?title ?illustratorLabel ?publisherLabel ?published</span>
WHERE
{
  ?book wdt:P50 wd:Q35610.
  OPTIONAL { ?book wdt:P1476 ?title. }
  OPTIONAL { ?book wdt:P110 ?illustrator. }
  OPTIONAL { ?book wdt:P123 ?publisher. }
  OPTIONAL { ?book wdt:P577 ?published. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

כך מתקבלים משתנים נוספים (‎?title,‏ ‎?publisher וכו׳) אם הקביעה המתאימה קיימת, אך אם הקביעה לא קיימת, התוצאה לא נזרקת מהרשימה - המשתנה פשוט לא מוגדר.

נא לשים לב: חשוב מאוד להשתמש כאן בפסוקיות OPTIONAL נפרדות. אם שמים את כל השלישיות בפסוקית אחת, כמו פה -

SELECT ?book ?title ?illustratorLabel ?publisherLabel ?published
WHERE
{
  ?book wdt:P50 wd:Q35610.
  OPTIONAL {
    ?book wdt:P1476 ?title;
          wdt:P110 ?illustrator;
          wdt:P123 ?publisher;
          wdt:P577 ?published.
  }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Try it!

- מיד יתחוור לך שרוב התוצאות לא כוללות מידע נוסף כלשהו. זה כיוון שפסוקית רשות עם מגוון שלישיות מוצאת אותן רק כאשר כל השלישיות האלו מסופקות. כלומר: אם לספר יש כותרת, מאייר, הוצאת ספרים ותאריך פרסום, אז פסוקית הרשות תמצא אותן, והערך האלו מוקצים למשתנים המתאימים. אך אם לספר יש, למשל, כותרת אך לא מאייר, כל פסוקית הרשות לא תמצא פריטים ולמרות שהתוצאה לא תיזרק מהרשימה, כל ארבעת המשתנים יישארו ריקים.

ביטויים, FILTER ו־BIND (סינון ואיגוד)

הסעיף הזה עלול להיראות פחות מאורגן מהשאר, כיוון שהוא מכסה נושא יחסית רחב ומגוון. העיקרון הבסיסי הוא שנרצה לעשות משהו עם ערך שעד כה בחרנו והחזרנו ללא הבחנה. וביטויים הן דרך לבטא את הפעולות האלה על ערכים. יש סוגים רבים של ביטויים, ומגוון רחב של דברים שאפשר לעשות איתם - אך קודם כל, נתחיל ביסודות: טיפוסי נתונים.

טיפוסי נתונים

לכל ערך ב־SPARQL יש טיפוס, שאומר לו איזה סוג של ערך הוא ומה אפשר לעשות איתו. הטיפוסים החשובים ביותר הם:

  • פריט, כמו wd:Q42 לציון Douglas Adams (Q42).
  • בוליאני, עם שני הערכים האפשריים true ו־false. ערכים בוליאנים לא מאוחסנים בקביעות, אך ביטויים רבים מחזירים ערך בוליאני, למשל: 2 < 3 (true) או "a" = "b" (false).
  • מחרוזת, קטע טקסט. ביטויי טקסט נכתבים בתוך מירכאות.
  • טקסט חד־לשוני, מחרוזת שמצורף לה תג שם. בביטוי, אפשר להוסיף את תג השפה אחרי המחרוזת עם הסימן @, למשל: "דאגלס אדמס"@he.
  • מספרים, שלמים (1) או עם נקודה עשרונית (1.23).
  • תאריכים. אפשר לציין ביטויי תאריכים על ידי הוספת ‎^^xsd:dateTime (תלוי רישיות – ‎^^xsd:datetime לא יעבוד!) לתאריך בתסדיר ISO 8601 מחרוזת תאריך: ‎"2012-10-29"^^xsd:dateTime‎.

פעולות

סימני פעולות החשבון הנפוצות זמינים: +,‏ -,‏ *,‏ / כדי להוסיף, להחסיר, להכפיל או לחלק מספרים, code><,‏ >,‏ =,‏ <=,‏ >= כדי להשוות ביניהם. בדיקת אי השוויון ≠ נכתבת כך: !=. השוואה מוגדרת גם לסוגים אחרים, למשל: "abc" < "abd" זה ביטוי אמת (השוואה מילונית), וגם "2016-01-01"^^xsd:dateTime > "2015-12-31"^^xsd:dateTime ו־wd:Q4653 != wd:Q283111. ואפשר לשלב תנאים בוליאניים עם && (וגם לוגי: a && b הוא ביטוי אמת אם גם a וגם b הם ביטויי אמת) וגם || (או לוגי: a || b הוא אמת אם אחד מהביטויים (או שניהם) of a וגם b הם ביטויי אמת).

FILTER (סינון)

  מידע לחלופה שלעיתים היא מהירה יותר ל־FILTER, אפשר לעיין ב־MINUS, הינה דוגמה.

FILTER(condition). היא פסוקית שאפשר להוסיף לשאילתת ה־SPARQL שלך כדי לסנן את התוצאות. בתוך הסוגריים, אפשר להוסיף כל ביטוי מסוג בוליאני, ורק התוצאות בהן הביטוי מחזיר אמת יהיו בשימוש.

למשל, כדי לקבל רשימה של כל האנשים שנולדו ב־2015, קודם נמשוך את כל האנשים עם תאריך הלידה שלהם -

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } 
}

- ואז לסנן את זה להחזיר רק את התוצאות שבהן שנת הלידה היא 2015. יש שתי דרכים לעשות את זה: לחלץ את השנה של התאריך עם הפונקציה YEAR ולבדוק שהיא 2015 -

FILTER(YEAR(?dob) = 2015).

- או לבדוק שהתאריך הוא בין 1 בינואר, 2015 (כולל) ועד 1 בינואר, 2016 (לא כולל):

FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).

אפשר לומר שהאפשרות הראשונה היא יותר ישירה אך מסתבר שהשנייה היא מהירה יותר, אז בואו נשתמש בה:

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". } 
}
Try it!

שימוש אפשרי ב־FILTER קשור לתוויות. שירות התוויות הוא מאוד שימושי אם נרצה רק להציג תווית של משתנה. אך כדי לעשות כל מיני דברים עם התווית - למשל: לבדוק אם היא מתחילה ב־„Mr. ‎” - נראה שזה למעשה לא עובד:

SELECT ?human ?humanLabel
WHERE
{
  ?human wdt:P31 wd:Q15632617.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
  #This FILTER does not work!
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
}
Try it!

השאילתה הזאת מוצאת את כל המופעים של fictional human (Q15632617) ובודקת האם התוויות שלהם מתחילות ב־„Mr. ‎”‏ (STRSTARTS הוא קיצור של הביטוי „string starts [with]” (המחרוזת מתחילה ב־), יש גם את STRENDS (המחרוזת מסתיימת ב־) ואת CONTAINS (המחרוזת מכילה)). הסיבה שזה לא עובד היא ששירות התוויות מוסיף את המשתנים שלו מאוד מאוחר במהלך הערכת השאילתה, בנקודה שבה אנחנו מנסים לסנן לפני ‎?humanLabel, שירות התוויות עדיין לא יצר את המשתנה הזה.

למרבה המזל, שירות התוויות הוא לא הדרך היחידה שבה אפשר לקבל את תווית הפריט. תוויות מאוחסנות גם הן כשלישיות רגילות, שמשתמשות בנשוא rdfs:label. כמובן שהכוונה היא לכל התוויות, לא רק לאלו שבאנגלית, אם אנחנו רוצים רק את התוויות באנגלית, נצטרך לסנן לפי שפת התווית:

FILTER(LANG(?label) = "en").

הפונקציה LANG מחזירה את השפה של מחרוזת חד־לשונית, וכאן אנו בוחרים רק את התוויות האלה באנגלית. השאילתה המלאה היא:

SELECT ?human ?label
WHERE
{
  ?human wdt:P31 wd:Q15632617;
         rdfs:label ?label.
  FILTER(LANG(?label) = "[AUTO_LANGUAGE]").
  FILTER(STRSTARTS(?label, "Mr. ")).
}
Try it!

אנחנו מקבלים את התווית עם השלישייה ?human rdfs:label ?label, מגבילים אותה לתוויות באנגלית ואז בודקים אם היא מתחילה ב־„Mr. ‎”.

אפשר גם להשתמש ב־FILTER עם ביטוי רגולרי. כמו בדוגמה הבאה

SELECT ?item ?itemLabel ?bblid
WHERE {  
    ?item wdt:P2580 ?bblid .
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }  
    FILTER(!REGEX(STR(?bblid), "[\\.q]")) 
}
Try it!

אם אילוץ התסדיר למזהה הוא ‎[A-Za-z][-.0-9A-Za-z]{1,}:

SELECT ?item ?itemLabel ?bblid
WHERE {  
    ?item wdt:P2580 ?bblid .
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }  
    FILTER(!REGEX(STR(?bblid), "^[A-Za-z][-.0-9A-Za-z]{1,}$"))
}
Try it!

אפשר לסנן החוצה רכיבים מסוימים באופן הבא

FILTER ( ?item not in ( wd:Q4115189,wd:Q13406268,wd:Q15397819 ) )

אפשר לסנן ושיופיעו רכיבים שלא מולאו:

FILTER ( NOT EXISTS { ?item  wdt:P21 [] } )


BIND,‏ BOUND,‏ IF (איגוד, תיחום, ברירה)

בשלוש יכולות אלו משתמשים בדרך כלל בשילוב זו עם זו, נתחיל בהסבר על שלושתן ואז נעבור לכמה דוגמאות.

בפסוקית ‪BIND(ביטוי AS ?variable).‬ אפשר להשתמש כדי להקצות את תוצאת הביטוי למשתנה (בדרך כלל משתנה חדש אבל אפשר גם לדרוס קיימים).

BOUND(?variable) בודק אם משתנה תחום לערך (מחזיר true (אמת) או false (שקר)). שימושי מאוד למשתנים שהוקמו על ידי פסוקית OPTIONAL.

IF(condition,thenExpression,elseExpression) מפוענח לכדי thenExpression אם condition (תנאי) מפוענח לכדי true, ול־elseExpression אם condition מפוענח ל־false. כלומר, IF(true, "yes", "no") יפוענח ל־"yes", ו־IF(false, "great", "terrible") יפוענח ל־"terrible".

ב־BIND אפשר להשתמש כדי לאגד את תוצאות חלק מהחישוב למשתנה חדש. זאת יכולה להיות תוצאת ביניים של חישוב גדול יותר או פשוט תוצאה ישירות של השאילתה. למשל, כדי לאתר את גיל הנידונים לעונש מוות:

SELECT ?person ?personLabel ?age
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?born;
          wdt:P570 ?died;
          wdt:P1196 wd:Q8454.
  BIND(?died - ?born AS ?ageInDays).
  BIND(?ageInDays/365.2425 AS ?ageInYears).
  BIND(FLOOR(?ageInYears) AS ?age).
  # or, as one expression:
  #BIND(FLOOR((?died - ?born)/365.2425) AS ?age).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

ב־BIND אפשר גם להשתמש כדי פשוט לאגד ערכים קבועים למשתנים כדי לשפר את נוחות הקריאה. למשל, שאילתה שמוצאת את כל הכמרות (נשים שמכהנות בתפקידי כמורה):

SELECT ?woman ?womanLabel
WHERE
{
  ?woman wdt:P31 wd:Q5;
         wdt:P21 wd:Q6581072;
         wdt:P106 wd:Q42603.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

אפשר גם לשכתב לצורה הזאת:

SELECT ?woman ?womanLabel
WHERE
{
  BIND(wdt:P31 AS ?instanceOf).
  BIND(wd:Q5 AS ?human).
  BIND(wdt:P21 AS ?sexOrGender).
  BIND(wd:Q6581072 AS ?female).
  BIND(wdt:P106 AS ?occupation).
  BIND(wd:Q42603 AS ?priest).
  ?woman ?instanceOf ?human;
         ?sexOrGender ?female;
         ?occupation ?priest.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

החלק המשמעותי של השאילתה, מ־‎?woman ועד ‎?priest.‎, הוא עכשיו קריא יותר. עם זאת, מקטע ה־BIND הגדול שלפני די מפריע, לכן צריך להשתמש בטכניקה הזאת במשורה. (בממשק המשתמש של WDQS, אפשר גם לרחף עם העכבר מעל תיאור הישות שלך, ואז ‎?female זה רק קריא יותר מ־wd:Q6581072 אם מתעלמים מהיכולת הזאת.)

בביטויי IF בדרך כלל נעשה שימוש בתנאי-ביטויים שנבנו עם BOUND. למשל, נניח שיש לך שאילתה שמציגה כל מיני אנשים ובמקום פשוט להציג את התווית שלהם, נרצה להציג את המאפיין pseudonym (P742) שלהם אם יש להם כזה, ורק להשתמש בתווית אם לא קיים שם בדוי. לשם כך, יש לבחור את השם הבדוי בפסוקית OPTIONAL (זה חייב להיות בגדר רשות – אנחנו לא רוצים לנפות תוצאות שאין להן שם בדוי), ואז להשתמש ב־BIND(IF(BOUND(…‎ כדי לבחור או את השם הבדוי או את התווית.

SELECT ?writer ?label
WHERE
{
  # French writer born in the second half of the 18th century
  ?writer wdt:P31 wd:Q5;
          wdt:P27 wd:Q142;
          wdt:P106 wd:Q36180;
          wdt:P569 ?dob.
  FILTER("1751-01-01"^^xsd:dateTime <= ?dob && ?dob < "1801-01-01"^^xsd:dateTime).
  # get the English label
  ?writer rdfs:label ?writerLabel.
  FILTER(LANG(?writerLabel) = "en").
  # get the pseudonym, if it exists
  OPTIONAL { ?writer wdt:P742 ?pseudonym. }
  # bind the pseudonym, or if it doesn’t exist the English label, as ?label
  BIND(IF(BOUND(?pseudonym),?pseudonym,?writerLabel) AS ?label).
}
Try it!

מאפיינים נוספים שאפשר להשתמש בהם באופן הזה הם nickname (P1449), posthumous name (P1786) וtaxon common name (P1843) – כל מקום שהגיוני להשתמש בו בסוג כלשהו של „נסיגה/גיבוי”.

אפשר גם לשלב את BOUND עם FILTER כדי לוודא שלפחות אחת מבין הדרישות במקטעי ה־OPTIONAL מולאו. למשל, בואו ניקח את האסטרונאוטים שהגיעו לירח, לרבעות החברים של Apollo 13 (Q182252) (מספיק קרוב, לא?). אי אפשר לבטא את האילוץ הזה כנתיב מאפיין יחיד, לכן אנחנו צריכים פסוקית OPTIONAL עבור „חברים במשימת ירח כלשהי” ואחת נוספת עבור „חברי 13”. אבל אנחנו רוצים לבחור רק את התוצאות האלו שבהן לפחות אחד מהתנאים האלה הוא אמת (true).

SELECT ?astronaut ?astronautLabel
WHERE
{
  ?astronaut wdt:P31 wd:Q5;
             wdt:P106 wd:Q11631.
  OPTIONAL {
    ?astronaut wdt:P450 ?mission.
    ?mission wdt:P31 wd:Q495307.
  }
  OPTIONAL {
    ?astronaut wdt:P450 wd:Q182252.
    BIND(wd:Q182252 AS ?mission).
  }
  FILTER(BOUND(?mission)).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

COALESCE (החזרת הערך התקין מבין האפשרויות)

אפשר להשתמש בפונקציית COALESCE כקיצור לתבנית ‎BIND(IF(BOUND(?x), ?x, ?y) AS ?z).‎ לנסיגות כדי שצוינו להלן: היא מקבלת מספר ביטויים ומחזיר את הראשון שמפוענח ללא שגיאה. למשל, הנסיגה של „השם הבדוי” הבא

BIND(IF(BOUND(?pseudonym),?pseudonym,?writerLabel) AS ?label).

אפשר לכתוב בצורה יותר מתומצתת בתור

BIND(COALESCE(?pseudonym, ?writerLabel) AS ?label).

ותמיד קל להוסיף תווית נסיגה נוספת למקרה שגם ‎?writerLabel לא מוגדר:

BIND(COALESCE(?pseudonym, ?writerLabel, "<no label>") AS ?label).

קיבוץ

עד השלב הזה, כל השאילתות שראינו הן שאילתות שמצאו את כל הפריטים שעונים על חלק מהתנאים, בחלק מהמקרים, כללנו גם קביעות נוספות על הפריט (ציורים עם החומרים, ספרים של ארתור קונאן דויל עם כותרת ואיור).

אבל זה מאוד נפוץ לא לרצות רשימה ארוכה של כל התוצאות. במקום, נוכל לשאול שאלות כאלו:

  • כמה ציורים צוירי על קנבס / עץ צפצפה / וכו׳?
  • מה כמות האוכלוסיה הגדולה ביותר של ערים בכל מדינה?
  • מה המספר הכולל של אקדחים שנוצרים על ידי כל יצרן ויצרן?
  • מי מפרסם, בממוצע, את הספרים הארוכים ביותר?

אוכלוסיות עירוניות

בואו נתמקד בשאלה שנייה כרגע. קל יחסית לכתוב שאילתה שמציגה את כל הערים לרבות האוכלוסיה והמדינה שהן נמצאות בה, תוך סידור התוצאות לפי מדינה:

SELECT ?country ?city ?population
WHERE
{
  ?city wdt:P31/wdt:P279* wd:Q515;
        wdt:P17 ?country;
        wdt:P1082 ?population.
}
ORDER BY ?country
Try it!

(לתשומת ליבך: השאילתה הזאת מחזיקה המון תוצאות, שיכולות להאט את הדפדפן שלך. אולי עדיף להוסיף פסוקית LIMIT.)

מאחר שאנחנו מסדרים את התוצאות לפי מדינה, כל הערים ששיכים למדינה יוצרים מקטע אחד ארוך בתוצאות. כדי למצוא את כמות האוכלוסיה הגדולהל ביותר במקטע הזה, נרצה להתייחס למקטע כקבוצה ולכנס את כל ערכי האוכלוסיה הפרטניים לערך אחד: המרבי. את זה אפשר לעשות עם פסוקית GROUP BY (קיבוץ לפי) מתחת למקטע ה־WHERE (כאשר) ופונקציית כינוס (MAX) בפסוקית ה־SELECT.

SELECT ?country (MAX(?population) AS ?maxPopulation)
WHERE
{
  ?city wdt:P31/wdt:P279* wd:Q515;
        wdt:P17 ?country;
        wdt:P1082 ?population.
}
GROUP BY ?country
Try it!

החלפנו את ORDER BY (סידור לפי) ב־GROUP BY (קיבוץ לפי). ההשפעה של זה היא שכל התוצאות עם אותו ערך ב־‎?country תקובצנה יחד לתוצאה אחת. משמעות הדבר היא שצריך לשנות את גם את פסוקית ה־SELECT. אילו היינו משאיכים את פסוקית ה־SELECT ?country ?city ?population הישנה, אילו ?city ו־?population יוחזרו? כדאי לזכור, יש מגוון תוצאות בתוצאה היחידה הזאת, לכולן יש את אותו ערך ב־‎?country, כך שנוכל לבחור את זה, אך מאחר שלכל אחת מהן יכול להיות ‎?city ו־‎?population שונים, עלינו לספר ל־WDQS איזה מהערכים האלה לבחור. זאת העבודה של פונקציית הכינוס. במקרה הזה, השתמשנו ב־MAX: מתוך כל ערכי ה־‎?population, נבחר את המרבי לתוצאה המקובצת. (אנחנו גם צריכים לתת לערך הזה שם חדש עם המבנה AS (בתור), אבל זה פרט שולי.)

זאת התבנית הכללית לכתיבת שאילתות קיבוץ: לכתוב שאילתה רגילה שמחזירה את הנתונים המבוקשים (ללא קיבוץ, עם הרבה תוצאות לכל „קבוצה”), לאחר מכן להוסיף פסוקית GROUP BY ולהוסיף פונקציית כינוס לכל המשתנים שאינם מקובצים בפסוקית ה־SELECT.

חומרי ציור

בואו ננסה את זה עם שאלה נוספת: כמה ציורים צוירו על כל סוג של חומר? קודם כל נכתוב שאילתה שרק מחזירה את כל הציורים יחד עם החומר עליהם צוירו. (כדאי לקחת בחשבון להשתמש רק בקביעות made from material (P186) כאלו שהן עם מבחין applies to part (P518)painting support (Q861259).)

SELECT ?material ?painting
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
}
Try it!

עכשיו, צריך להוסיף פסוקית GROUP BY על ‎?material, ואז להוסיף פונקציית כינוס על המשתנה השני שנבחר (‎?painting). במקרה הזה, אנחנו מעוניינים במספר הציורים, פונקציית הכינוס לחישוב הזה היא COUNT.

SELECT ?material (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
}
GROUP BY ?material
Try it!

אחת הבעיות עם זה היא שאין לנו את התווית לחומרים, לכן לא כל כך נוח לפענח את התוצאות. אם פשוט נוסיף את משתנה התווית, נקבל שגיאה:

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material
Try it!

Bad aggregate

„כינוס שגוי” (Bad aggregate) היא הודעת שגיאה שמאוד נפוץ לפגוש כשעובדים עם שאילתות קיבוץ, המשמעות היא שאחד מהמשתנים צריך פונקציית כינוס אבל אין לו כזאת, או שיש לו פונקציית כינוס אבל לא אמורה להיות לו. במקרה הזה, מנגנון WDQS חושב שיכולים להיות מגוון ‎?materialLabel על כל ‎?material (למרות שאנחנו יודעים שזה לא יכול להיות), ולכן הוא מתלונן שלא צוינה פונקציית כינוס למשתנה הזה.

פתרון אחד הוא ליצור קיבוץ על מספר משתנים. אם מציגים מספר משתנים בפסוקית ה־GROUP BY, יש תוצאה אחת לכל שילוב של המשתנים האלה ואפשר לבחור את כל המשתנים האלה בלי פונקציית כינוס. במקרה הזה, נקבץ גם על גבי ‎?material וגם על גבי ‎?materialLabel.

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material ?materialLabel
Try it!

כמעט סיימנו עם השאילתה - רק עוד שיפור קטן: אנחנו רוצים לראות את החומרים השכיחים ביותר בהתחלה. למזלנו, מותר לנו להשתמש במשתנים החדשים המכונסים מפסוקית ה־SELECT, (כאן הם נקראים ‎?count) בפסוקית ORDER BY כך שזאת משימה די פשוטה:

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material ?materialLabel
ORDER BY DESC(?count)
Try it!

לשם התרגול, בואו נעשה גם את שאר השאילתות.

אקדחים לפי יצרן

מס מספר האקדחים הכולל שמיוצר על ידי כל אחד מהיצרנים?

מוציאים לאור לפי מספר דפים

מה מספר הדפים הממוצע (פונקציה: AVG) של ספרים לפי מוציא לאור?

HAVING (שיש לו)

תוספת קטנה לשאילתה האחרונה - אם מסתכלים על התוצאות, אפשר להבחין שלתוצאה המובילה יש ממוצע גדול בצורה מוגזמת, יותר מפי עשרה מהמקום השני. חקירה שטחית חושפת שזה כיוון שאותו מוציא לאור (UTET (Q4002388)) פרסם רק ספר אחד עם קביעה מסוג number of pages (P1104), Grande dizionario della lingua italiana (Q3775610), מה שמטה קצת את התוצאות. כדי להסיר חריגות כאלה, אפשר לבחור רק מוציאים לאור שהוציא לפחות שני ספרים עם קביעות מסוג number of pages (P1104) בוויקינתונים.

איך עושים את זה? בדרך כלל, נגדיל את התוצאות עם פסוקית FILTER, אבל במקרה הזה אנחנו רוצים להגביל לפי הקבוצה (מספר הספרים), לא על כל תוצאה בנפרד. אפשר לעשות את זה עם פסוקית HAVING (שיש לו), שאפשר להוסיף מייד לאחר הפסוקית GROUP BY והיא מקבלת ביטוי באותו האופן כמו FILTER:

SELECT ?publisher ?publisherLabel (AVG(?pages) AS ?avgPages)
WHERE
{
  ?book wdt:P123 ?publisher;
        wdt:P1104 ?pages.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?publisher ?publisherLabel
HAVING(COUNT(?book) > 1)
ORDER BY DESC(?avgPages)
Try it!

סיכום על פונקציות כינוס

הינה תקציר של פונקציות הכינוס הזמינות:

  • COUNT: מספר הרכיבים. אפשר גם לכתוב COUNT(*) כדי לספור את כל התוצאות.
  • SUM,‏ AVG: הסיכום או הממוצע של כל הרכיבים, בהתאמה. אם הרכיבים אינם מספרים תתקבלנה תוצאות מוזרות.
  • MIN,‏ MAX: הערך הקטן או הגדול ביותר מבין כל הרכיבים, בהתאמה. עובד בכל סוגי הערכים; מספרים מסודרים לפי הגודל, מחרוזות וסוגים אחרים מילונית.
  • SAMPLE: כל רכיב שהוא. על פי רוב זה שימושי אם ברור לך שיש תוצאה אחת או אם לא אכפת לך איזה ערך מוחזר.
  • GROUP_CONCAT: משרשרת את כל הרכיבים אחד אחרי השני. שימושי, למשל, אם נרצה תוצאה אחת בלבד לפריט אבל לכלול מגוון פרטי מידע למאפיין שיש בו מספר קביעות לפריט הזה, כמו למשל עיסוק של אדם. את תחומי העיסוק השונים אפשר לקבץ מחדש ולשרשר כדי שיופיעו במשתנה אחד בלבד במקום במספר שורות. אם זה מסקרן אותך, אפשר לחפש את זה במפרט של SPARQL.

בנוסף, אפשר להוסיף מבחין DISTINCT לכל אחת מהפונקציות האלה כדי להעלים את התוצאות הכפולות. למשל, אם יש שתי תוצאות אך לשתיהן יש את אותו הערך ב־‎?var, אז COUNT(?var) תחזיר 2 אבל COUNT(DISTINCT ?var) תחזיר 1 בלבד. בדרך כלל צריך להשתמש ב־DISTINCT כאשר השאילתה שלך יכולה להחזיר את אותו הפריט מספר פעמים - זה יכול לקרות אם, למשל, בחרת להשתמש ב־‎?item wdt:P31/wdt:P279* ?class, וישנם מספר נתיבים מ־‎?item אל ‎?class: תתקבל תוצאה חדשה לכל אחד מהנתיבים האלה, למרות שכל הערכים בתוצאה זהים. (אם לא קיבצת, אפשר לסלק את התוצאות הכפולות האלה על ידי התחלת השאילתה עם SELECT DISTINCT במקום רק SELECT.)

wikibase:Label וכינוסים

שאילתה כמו זו, שמחפשת את כל אנשי האקדמיה עם אזרחות ביותר משתי מדינות בוויקינתונים, לא מציגה את שמות המדינות האלה בעמודה ‎?citizenships:

select ?person ?personLabel (group_concat(?citizenshipLabel;separator="/") as ?citizenships) {
  # find all academics
  ?person wdt:P106 wd:Q3400985 ;   
          wdt:P27  ?citizenship .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} group by ?person ?personLabel having (count(?citizenship) > 2)
Try it!

כדי להציג את ‎?citizenships, יש לתת ל־‎?personLabel ול־‎?citizenshipLabel שם מפורש בקריאת השירות wikibase:label באופן הבא:

  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". 
    ?citizenship rdfs:label ?citizenshipLabel .
    ?person      rdfs:label ?personLabel .
  }

השאילתה הבאה עובדת כצפוי:

select ?person ?personLabel (group_concat(?citizenshipLabel;separator="/") as ?citizenships) {
  ?person wdt:P106 wd:Q3400985 ;
          wdt:P27  ?citizenship .
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". 
    ?citizenship rdfs:label ?citizenshipLabel .
    ?person      rdfs:label ?personLabel .
  }
} group by ?person ?personLabel having (count(?citizenship) > 2)
Try it!

VALUES (ערכים)

אפשר לבחור פריטים לפי רשימת פריטים:

SELECT ?item ?itemLabel ?mother ?motherLabel WHERE {
  VALUES ?item { wd:Q937 wd:Q1339 }
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

אפשר גם לבחור לפי רשימה של ערכים של מאפיין מסוים:

SELECT ?item ?itemLabel ?mother ?motherLabel ?ISNI WHERE {
  VALUES ?ISNI { "000000012281955X" "0000000122764157" }
  ?item wdt:P213 ?ISNI.
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

VALUES יכול לעשות אף יותר ולבנות ספירות של ערכים אפשריים למספר (או מגוון) של משתנים. למשל, נניח שנרצה להשתמש בתוויות (מוכרות) מותאמות אישית לאנשים שנספרן בדוגמה הראשונה ל„ערך”. לאחר מכן אפשר להשתמש בפסוקית „values” באופן הבא: VALUES (?item ?customItemLabel) { (wd:Q937 "Einstein") (wd:Q1339 "Bach") } מה שייודא שכל עוד של־?item יש את הערך wd:Q937 בתוצאה, הערך של ‎?customItemLabel עצמו הוא Einstein וכאשר ל־?item יש את הערך wd:Q1339, הערך של ‎?customItemLabel הוא Bach.

SELECT ?item ?customItemLabel ?mother ?motherLabel WHERE {
  VALUES (?item ?customItemLabel) { (wd:Q937 "Einstein") (wd:Q1339 "Bach") }
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

ועוד הרבה מעבר…

המדריך הזה מסתיים כאן, אך לא SPARQL: יש עדיין המון שעדיין לא הראיתי - מעולם לא הבטחתי שזה יהיה מדריך שלם! אם הגעת עד לשלב הזה, כבר יש לך ידע די מוצק בנוגע ל־WDQS ואמורה להיות לך יכולת לכתוב כמה שאילתות רבות עוצמה במיוחד. אבל אם מעניין אותך ללמוד אפילו עוד, הנה מספר דוגמאות שאפשר לעיין בהן:

  • תת־שאילתות. אפשר להוסיף עוד שאילתה שלמה בסוגריים מסולסלים ({ SELECT ... WHERE { ... } LIMIT 10 }), והתוצאות תהיינה גלויות בפני השאילתה החיצונית. (אם יש לך ניסיון ב־SQL, זה דורש קצת חשיבה מחדש על כל הרעיון הזה - תת־שאילתות של SPARQL הן לחלוטין „מלמטה למעלה” ואינן יכולות להשתמש בערכים משאילתה חיצונית, כמו שיכולה „תת־שאילתות מתואמות” ב־SQL.)
  • MINUS מאפשר לך לבחור תוצאות שאינן מתאימות לחלק מתבניות התרשימים. FILTER NOT EXISTS הוא בעיקרו שקול לו (ניתן לעיין במפרט של SPARQL כדי לראות דוגמה שבה יש ביניהם הבדל), אבל - לפחות ב־WDQS - איטי באופן משמעותי.

המקור העיקרי שלך לנושאים האלו ולאחרים הוא המפרט של SPARQL.

כמו כן, אפשר לעיין במדריך של SPARQL בוויקיספר ובמדריך הזה מאת data.world.

וכמובן, ישנם כמה חלקים בוויקינתונים שעדיין חסרים, כגון הפניות, דיוק עשרוני (100±2.5), ערכים עם יחידות (שני קילוגרמים), נק׳ ציון גאוגרפיות, קישורי בינוויקי, קביעות על מאפיינים ועוד. אפשר לראות איך מכניסים אותם לתבניות של שלישיות תחת mw:Wikibase/Indexing/RDF תבנית היטל.

ר׳ גם