How to filter for a condition with two columns? - sparql

For a course I follow I have to write several SPARQL queries about Lego sets. I am interested in finding out if there is a Lego theme which has a single package type.
I have the following SPARQL query:
select distinct ?theme ?package_type (count(?theme) as ?amount_of_lego_sets)
where{
?Lego_set rdf:type wd:Q58780257 .
?Lego_set sch:audienceType ?audience .
?Lego_set ex:has_package_information ?package_info .
?audience ex:belongs_to_theme ?theme .
?package_info ex:has_packaging_type ?package_type .
} group by ?theme ?package_type
order by ?theme
Which produces the following output:
As you can see there is one set that has the theme “4 Juniors” and the package type “Polybag”. Now, I am interested in themes like Advanced models or Action Wheelers which only have a single package type. However, I found it challenging to filter for these themes.
What modification to my query could I implement to remove themes which have sets that have more than one package type?

This is an interesting question. I would use FILTER NOT EXISTS to add an atom to the query body, where we make sure that the theme doesn't have two types of packages, like this:
FILTER NOT EXISTS {
?Lego_set2 sch:audienceType ?audience2 .
?Lego_set2 ex:has_package_information ?package_info2 .
#Notice that the 'theme' variable must be the same as the outer query
?audience2 ex:belongs_to_theme ?theme .
?package_info2 ex:has_packaging_type ?package_type1, ?package_type2
FILTER(?pakage_type1 != ?package_type2)}
Thus your full query should be something like:
select distinct ?theme ?package_type (count(?theme) as ?amount_of_lego_sets)
where{
?Lego_set rdf:type wd:Q58780257 .
?Lego_set sch:audienceType ?audience .
?Lego_set ex:has_package_information ?package_info .
?audience ex:belongs_to_theme ?theme .
?package_info ex:has_packaging_type ?package_type .
FILTER NOT EXISTS {
?Lego_set2 sch:audienceType ?audience2 .
?Lego_set2 ex:has_package_information ?package_info2 .
#Notice that the 'theme' variable must be the same as the outer query
?audience2 ex:belongs_to_theme ?theme .
?package_info2 ex:has_packaging_type ?package_type1, ?package_type2
FILTER(?pakage_type1 != ?package_type2)}
} group by ?theme ?package_type
order by ?theme
You could also use the aggregation approach mentioned in the comments, but hopefully this one solves your problem.

Related

SPARQL query: OR in FILTER?

I would like to search court cases based on their short title, but I've noticed in the RDF records that this information is sometimes stored under one property (cdm:expression_case-law_parties) and sometimes under another (cdm:expression_title_alternative). I would like to filter on both simultaneously. The below query, where I'm trying to use an OR || in the FILTER) does not work. What is the appropriate way?
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
SELECT ?work ?expression ?ecli ?celex ?alttitle ?parties ?title
WHERE {
?work a ?class.
?expression cdm:expression_belongs_to_work ?work.
?expression cdm:expression_title ?title.
?expression cdm:expression_uses_language <http://publications.europa.eu/resource/authority/language/ENG>.
?work cdm:case-law_ecli ?ecli.
?work cdm:resource_legal_id_celex ?celex.
OPTIONAL{?expression cdm:expression_case-law_parties ?parties}
OPTIONAL{?expression cdm:expression_title_alternative ?alttitle}
FILTER(?class in (<http://publications.europa.eu/ontology/cdm#judgement>))
FILTER CONTAINS (?alttitle, "France v Commission") || (?parties, "France v Commission")}
LIMIT 15
From Stanislav Kralin's comment:
FILTER (CONTAINS (?alttitle, "France v Commission") || CONTAINS(?parties, "France v Commission"))

SPARQL SubQuery in Filter

SELECT ?Name FROM <http://.../biblio.rdf>
WHERE { ?Aut name ?Name . ?Pub author ?Aut . ?Pub conf ?Conf
FILTER (?Conf IN ( SELECT ?ConfX FROM <http://.../biblio.rdf>
WHERE { ?ConfX series "ISWC" }))}
I have taken the query from http://www.renzoangles.net/files/amw2011.pdf.
Getting the malformed query syntax error when I tried the above format in AWS Neptune.
Please help me fix the above query.
If you want to test that a triple is in the data, which seems to be the intention of the exampel of "FILTER IN SELECT " here, yuo can use FILTER EXISTS
FILTER EXISTS { ?Conf series "ISWC" }

SPARQL Restrict Number of Results for Specific Variable

Suppose I want to look for some first degree neighbors of Berlin. I ask the following query:
select ?s ?p where {
?s ?p dbr:Berlin.
}
Is it possible to put a restriction on the return result, such that there are at most 5 results for each unique value of ?p?
My attempts with subqueries all time out...
But, as potentially useful if not exactly perfect solution, maybe GROUP_CONCAT, MAX/MIN or SAMPLE are of use?
SELECT
?writer (GROUP_CONCAT(?namestring; SEPARATOR = " ") AS ?namestrings)
(MIN(?namestring) AS ?min_name)
(MAX(?namestring) AS ?max_name)
(SAMPLE(?namestring) AS ?random_name)
(SAMPLE(?namestring) AS ?another_random_name_that_may_unfortunately_be_the_same_again)
WHERE {
?writer wdt:P31 wd:Q5;
wdt:P166 wd:Q37922;
wdt:P735 ?firstname.
?firstname wdt:P1705 ?namestring.
}
GROUP BY ?writer
HAVING ((COUNT(?writer)) > 2 )
LIMIT 20
See it live here.
And, as you can see, SAMPLE is apparently evaluated only once, so using it repeatedly does not get you closer to five (different) samples.
(You can leave out the HAVING for your use. I only included it to restrict it to useful examples))

Why filter doesn't work in this context?

This is the query and the result:
As you see, I am filtering out the users that are bo:ania, so why do they still appear?
However, if I remove the widecard and select just the users ?user, bo:ania doesn't appear
I didn't provide a minimum data example because this is a question about how filter and wildcard work, not about a problem in extracting some data from a data set. However, if you need a minimum data, I'm more than happy to provide it.
?specificUser is bound to bo:ania by your VALUES statement. ?user is an entirely different binding defined by the other triple patterns. Your FILTER says to filter out results where ?user = bo:ania, and it appears to be doing that correctly, seeing that ?user is not bound to bo:ania in any of the results.
BTW, there isn't a need to use VALUES in this case unless you want to inspect multiple values. If it's just the one value, then the following would work, and not have you wondering why the binding to bo:ania is included in the result set:
SELECT *
WHERE {
?user a rs:user .
?user rs:hasRated ?rating .
?rating rs:hasRatingDate ?ratngDate .
FILTER (?ratingDates >= (now() -"P10000F"^^xsd:duration) )
FILTER (?user != bo:ania)
}

Group By not working in DBPedia

I am working in DBPedia. I am having a problem when using group by in Sparql.
I have this code:
SELECT ?res ?titulo
WHERE {
?res rdf:type <http://dbpedia.org/class/yago/JaguaresDeChiapasFootballers> .
?res rdfs:label ?titulo .
}
GROUP BY (?res)
LIMIT 15
I want to return a list of all in this type. But I only want to return one for each URI, I put the group by and it doesn’t work and I really don’t know why?
Can someone help me?
Your original query isn't legal SPARQL. If you paste it into the SPARQL query validator at sparql.org, you'll get the following message:
Non-group key variable in SELECT: ?titulo
If you group by ?res, then you can't select the non-group variable ?titulo. If you just want one ?titulo value per ?res, then you can use …
select ?res (sample(?titulo) as ?title)
…
SPARQL results
If you want a list of the titles, then you can use group_concat to concatenate the titles:
select ?res (group_concat(?titulo;separator=', ') as ?title)
…
SPARQL results