Projekt: Hesla Jednoty bratrské/výročí/2019/SPARQL

Jak používat klasifikační nálepkuTato stránka je součástí projektu:
Příslušnost: skupinová

Projekt: Hesla Jednoty bratrské/výročí/2019/SPARQL – na této stránce se pokusíme dohledat nějaká výročí na Wikidatech pomocí Wikidata/SPARQL.

Známé události – různé defenestrace

editovat

Začneme s tím, že:

  1. se podíváme na nějaké známé události, které jsme si už předtím vyhledali
  2. podíváme se, jaké záznamy na wikidatech jim přísluší
  3. pokusíme se dohledat tyto známé události nějakým skriptem
  4. pak se ten skript pokusíme nějak modifikovat, aby nám našel i to, co ještě neznáme
wdt:P31 wd:Q220277 # instance čeho / defenestrace
wdt:P361 wd:Q374696 # část čeho / Pražská defenestrace
wdt:P585 1419-07-30 # datum

Dohledáme všechny defenestrace:

SELECT * WHERE {
 ?event wdt:P31 wd:Q220277 .
}

Ukaž! – Našlo jen dvě defenestrace.

SELECT ?event ?eventLabel WHERE {
 ?event wdt:P31 wd:Q220277 .
 SERVICE wikibase:label { bd:serviceParam wikibase:language "cs, en". }
}

Ukaž!

event eventLabel
wd:Q688769 Pražská defenestrace (1419)
wd:Q13365740 Pražská defenestrace (1613)

Jsou to ty naše. Buď se jinde než v Praze nedefenestrovalo anebo je tam něco špatně na tom d:Q220277.

Zkusíme vyselektovat datum, ale nějak se nám to nedaří, podívám se tedy na d: Wikidata:SPARQL query service/queries/examples#Battles per year per country last 80 years a po inspiraci filtruju:

SELECT * WHERE {
 ?event wdt:P31 wd:Q220277 . # instance čeho / defenestrace
 ?event wdt:P585 ?date .
 FILTER (YEAR(?date) = 1419)
}

Ukaž!

event date
wd:Q688769 8. srpen 1419

Některé události ale mohou trvat delší dobu, tak je nutno použít d:Property:P580 = počátek nějakého stavu a d:Property:P582 = konec nějakého stavu.

SELECT * WHERE {
 ?event wdt:P31 wd:Q220277 . # instance čeho / defenestrace
 ?event wdt:P585 ?date .
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d1),(IF(!BOUND(?d2),?d3,?d2)),?d1) as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

event date d1 d2 d3 year
wd:Q688769 8. srpen 1419 8. srpen 1419 1419
wdt:P31 wd:Q220277 # instance čeho / defenestrace
wdt:P361 wd:Q374696 # část čeho / Pražská defenestrace
wdt:P585 23. 5. 1618gregoriánský # datum

Takže řádné zajímavé údaje ve srovnání s První pražskou tu nejsou, jen ta poznámka, že datum je už dle gregoriánského kalendáře.

Všechny události 1419

editovat

Tak teď zkusíme události roku 1419:

SELECT * WHERE {
 ?event wdt:P585 ?date .
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

Najde mi 14 událostí, mezi nimi i tu defenestraci d:Q688769.

Zkusím tedy do dotazu zahrnout i případy, kdy se jedná o nějaký proces s počátkem a koncem:

 SELECT * WHERE {
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d1),(IF(!BOUND(?d2),?d3,?d2)),?d1) as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

To mi našlo ale jen 4 události, v žádné není ?d2.

Tak je asi někde nějaká chyba, koukám na d:Wikidata:SPARQL tutorial#BIND, BOUND, IF

Zkusím to strukturovat:

 SELECT * WHERE {
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d1),           # condition: pokud není ?d1
           (IF(!BOUND(?d2),         # pak tedy condition: pokud není ani ?d2
                ?d3,?d2)),          # tak tedy ?d3, jinak ?d2
           ?d1)                 # jinak tedy ?d1
      as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

No si myslím, že by se mělo vycházet z toho ?d2, a pokud není, tak ty další ?d1 a ?d3, ale tuším, že to nakonec vyjde nastejno:

 SELECT * WHERE {
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d2),           # condition: pokud není ?d2
           (IF(!BOUND(?d1),         # pak tedy condition: pokud není ani ?d2
                ?d3,?d1)),          # tak tedy ?d3, jinak ?d2
           ?d2)                 # jinak tedy ?d2
      as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

Ano, tušil jsem správně, vyšlo to nastejno. Možná nejdřív musím zkusit najít ?d2 bez toho option, s tečkou na konci?? Ale moc by mi to nedávalo smysl

SELECT * WHERE {
 ?event wdt:P585 ?d2 .
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d2),           # condition: pokud není ?d2
           (IF(!BOUND(?d1),         # pak tedy condition: pokud není ani ?d2
                ?d3,?d1)),          # tak tedy ?d3, jinak ?d2
           ?d2)                 # jinak tedy ?d2
      as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
}

Ukaž!

No jo, dopadlo to, jak jsem předpokládal, našlo mi to všechno, kde je ?d2, ale ty s ?d1 a ?d3 už to nenašlo.

Momentálně nevím, co s tím, vznáším dotaz na FB do skupiny Wikidata CS.

No, zkusím se ještě podívat, co je to za těch 14 událostí:

SELECT ?date ?event ?eventLabel ?d1 ?d2 ?d3  WHERE {
 ?event wdt:P585 ?d2 .
 OPTIONAL {?event wdt:P580 ?d1} # počátek nějakého stavu
 OPTIONAL {?event wdt:P585 ?d2} # datum
 OPTIONAL {?event wdt:P582 ?d3} # konec nějakého stavu
 BIND(IF(!BOUND(?d2),           # condition: pokud není ?d2
           (IF(!BOUND(?d1),         # pak tedy condition: pokud není ani ?d2
                ?d3,?d1)),          # tak tedy ?d3, jinak ?d1
           ?d2)                 # jinak tedy ?d2
      as ?date)
 BIND(YEAR(?date) as ?year)
 FILTER (?year = 1419)
 SERVICE wikibase:label { bd:serviceParam wikibase:language "cs, en". }
}

Ukaž!

Dotaz běží, běží a furt nic...

Vypršel časový limit pro dotaz

No konečně to vyjelo. Ale nevím, jak si to přebrat :-(

Mezitím mi d:User:Matěj Suchánek na FB odpověděl, že by se to dalo dělat přes sjednocení (UNION), toto je jeho řešení:

SELECT ?event ?eventLabel ?eventDescription ?year ?date WHERE {
  {
    ?event wdt:P585 ?date .
  } UNION {
    ?event wdt:P580 ?date .
  } UNION {
    ?event wdt:P582 ?date .
  } .
  BIND( YEAR( ?date ) AS ?year ) .
  FILTER( ?year = 1419 ) .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" } .
}

Ukaž!

Tak to mi vyhodilo 20 odpovědí.

Další příklad nacházím přímo mezi příklady na Wikidata Query d: Wikidata:SPARQL_query_service/queries/examples#Recent Events:

#Recent Events
SELECT ?event ?eventLabel ?date
WHERE
{
	# find events
	?event wdt:P31/wdt:P279* wd:Q1190554.
	# with a point in time or start date
	OPTIONAL { ?event wdt:P585 ?date. }
	OPTIONAL { ?event wdt:P580 ?date. }
	# but at least one of those
	FILTER(BOUND(?date) && DATATYPE(?date) = xsd:dateTime).
	# not in the future, and not more than 31 days ago
	BIND(NOW() - ?date AS ?distance).
	FILTER(0 <= ?distance && ?distance < 31).
	# and get a label as well
	OPTIONAL {
		?event rdfs:label ?eventLabel.
		FILTER(LANG(?eventLabel) = "en").
	}
}
# limit to 10 results so we don't timeout
LIMIT 10

Ukaž!

Tak si to trochu upravíme:

#Events in the year 1419
SELECT ?event ?eventLabel ?date
WHERE
{
	# find events
	?event wdt:P31/wdt:P279* wd:Q1190554.  # instance čeho / nadtřída | událost
	# with a point in time or start date
	OPTIONAL { ?event wdt:P585 ?date. }    # datum (datum události)
	OPTIONAL { ?event wdt:P580 ?date. }    # od (počátek nějakého stavu)
	# but at least one of those
	FILTER(BOUND(?date) && DATATYPE(?date) = xsd:dateTime). # http://www.datypic.com/sc/xsd/t-xsd_dateTime.html http://books.xmlschemata.org/relaxng/ch19-77049.html
	# year 1419
	FILTER(YEAR(?date) = 1419) .
	# and get a label as well
	OPTIONAL {
		?event rdfs:label ?eventLabel.
		FILTER(LANG(?eventLabel) = "en").
	}
}
# limit to 20 results so we don't timeout
LIMIT 20

Ukaž!

I tak to trvá hrozně dlouho, nakonec:

Vypršel časový limit pro dotaz

Ani s LIMIT 5 se ničeho nedočkám. Nejspíš za to může ta konstrukce:

?event wdt:P31/wdt:P279* wd:Q1190554.

A jak potvrzuje d:User:Matěj Suchánek na FB, asi se v tom nemýlím. Zkusím zakomentovat tu hvězdičkovou konstrukci:

#Events in the year 1419
SELECT ?event ?eventLabel ?date
WHERE
{
	# find events
#	?event wdt:P31/wdt:P279* wd:Q1190554.  # instance čeho / nadtřída | událost
	# with a point in time or start date
	OPTIONAL { ?event wdt:P585 ?date. }    # datum (datum události)
	OPTIONAL { ?event wdt:P580 ?date. }    # od (počátek nějakého stavu)
	# but at least one of those
	FILTER(BOUND(?date) && DATATYPE(?date) = xsd:dateTime). # http://www.datypic.com/sc/xsd/t-xsd_dateTime.html http://books.xmlschemata.org/relaxng/ch19-77049.html
	# year 1419
	FILTER(YEAR(?date) = 1419) .
	# and get a label as well
	OPTIONAL {
		?event rdfs:label ?eventLabel.
		FILTER(LANG(?eventLabel) = "en").
	}
}
LIMIT 20

A hned dostanu 20 výsledků: Ukaž!

Ale pokud tam ten LIMIT nedám (zakomentuju), dostanu jen 14 výsledků. To fakt nechápu:

#Events in the year 1419
SELECT ?event ?eventLabel ?date
WHERE
{
	# find events
#	?event wdt:P31/wdt:P279* wd:Q1190554.  # instance čeho / nadtřída | událost
	# with a point in time or start date
	OPTIONAL { ?event wdt:P585 ?date. }    # datum (datum události)
	OPTIONAL { ?event wdt:P580 ?date. }    # od (počátek nějakého stavu)
	# but at least one of those
	FILTER(BOUND(?date) && DATATYPE(?date) = xsd:dateTime). # http://www.datypic.com/sc/xsd/t-xsd_dateTime.html http://books.xmlschemata.org/relaxng/ch19-77049.html
	# year 1419
	FILTER(YEAR(?date) = 1419) .
	# and get a label as well
	OPTIONAL {
		?event rdfs:label ?eventLabel.
		FILTER(LANG(?eventLabel) = "en").
	}
}
# LIMIT 20

Ukaž!

Tak ještě zkouším další příklad: d: Wikidata:SPARQL query service/queries/examples/cs#Locations of battles

#added before 2016-10
#defaultView:Map
SELECT ?label ?coord ?subj ?year
WHERE
{
	?subj wdt:P31 wd:Q178561 .
	?subj wdt:P625 ?coord .
	OPTIONAL {?subj wdt:P580 ?d1}
	OPTIONAL {?subj wdt:P585 ?d2}
  	OPTIONAL {?subj wdt:P582 ?d3}
	BIND(IF(!BOUND(?d1),(IF(!BOUND(?d2),?d3,?d2)),?d1) as ?date)
	BIND(YEAR(?date) as ?year)
	?subj rdfs:label ?label filter (lang(?label) = "en")
}

A tady nacházím z roku 1419 např.:

  • d: Q1468732 – bitva pod Vyšehradem – předtím nalezena
  • d: Q11156922 – bitva u Živohoště – předtím nalezena
  • d: Q513007 – bitva u Záblatí (poblíž Prachatic) – předtím nenalezena. Jak to?

Jen se ještě divím, že:

se zobrazuje někde na hranicích s Rakouskem u Nové Bystřice. Asi by to chtělo něco opravit.