Selecting some distinct and some not-distinct tags in SPARQL - distinct

I'm trying to query DBPedia for a list of properties relating to a given class in the ontology, but since the human-readable "labels" aren't always clear, I'd also like to provide an example from the database. The problem is that while I want to select all distinct properties, I only want a single example of each property. Here's how my query looks without capturing the example:
SELECT DISTINCT ?prop ?title WHERE {
?thing ?prop [].
?thing a <http://dbpedia.org/ontology/Currency>.
?prop rdf:type rdf:Property.
?prop rdfs:label ?title.
} ORDER BY DESC(COUNT(DISTINCT ?thing))
LIMIT 100
If I change it in this way, I start getting duplicate values for ?prop:
SELECT DISTINCT ?prop ?title ?example WHERE {
?thing ?prop ?example.
?thing a <http://dbpedia.org/ontology/Currency>.
?prop rdf:type rdf:Property.
?prop rdfs:label ?title.
} ORDER BY DESC(COUNT(DISTINCT ?thing))
LIMIT 100
I'm very new to using SPARQL and database queries in general, so it's not at all clear to me how to do this. Ideally, I'd have something like DISTINCT(?prop) ?title ?example, which selects every unique value for prop, and returns its title and an example.

In your second queries the distinct applies to the combination of values of ?prop ?title and ?example. Therefore you're not getting any duplicates, for instance for the following two rows obtained in the second query:
dbpedia2:subunitName "subunit name "#en "cent"#en
dbpedia2:subunitName "subunit name "#en "centavo"#en
they aren't duplicates because the third row ?example has two different values "cent"#en and "centavo"#en
One posible way to solve this is to use GROUP BY and MIN to get just the lowest ranked value for ?label and ?example, i.e:
SELECT ?prop MIN(?title) MIN(?example) WHERE {
?thing ?prop ?example.
?thing a <http://dbpedia.org/ontology/Currency>.
?prop rdf:type rdf:Property.
?prop rdfs:label ?title.
} GROUP BY ?prop

Here is an alternative way to achieve what you want with subqueries:
SELECT ?prop ?title ?example
WHERE
{
?thing a <http://dbpedia.org/ontology/Currency>.
?prop rdf:type rdf:Property.
{ SELECT ?title ?example WHERE { ?thing ?prop ?example . ?prop rdfs:label ?title. } LIMIT 1 }
}
LIMIT 100
This has the advantage that it is SPARQL 1.1 standards compliant, as I stated in my comment ordering by an aggregate is not permitted by the standard so you are using a vendor specific extension which will limit the portability of your query.
If you do want to order by an aggregated value in a way that is portable across SPARQL 1.1 implementations then you must first project it like so:
SELECT ?s (COUNT(?p) AS ?predicates) WHERE
{
?s ?p ?o
} GROUP BY ?s ORDER BY DESC(?predicates)

If you don't care about the example but you care about speed, SAMPLE can be much faster than GROUP BY
SELECT ?prop (SAMPLE(?title) AS ?title) (SAMPLE(?example) AS ?example)
WHERE {
?thing ?prop ?example.
?thing a <http://dbpedia.org/ontology/Currency>.
?prop rdf:type rdf:Property.
?prop rdfs:label ?title.
} LIMIT 100
You probably won't notice the difference on dbpedia since it caches query results, but I noticed a huge difference when using other endpoints.
I ran into the same issue op had while creating an autocomplete service that queries multiple sparql endpoints. I needed to find a single link related to a search term, of which the link itself wasn't very important, but the speed of the query was very important.

Related

"ID is not in resultset" error in Spring repo, but works in PGA

I got a very basic query which gets a top 10 of searched words:
select distinct keyword, sum (amount) as keyword_amount from search group by keyword order by keyword_amount DESC
This works fine in PostGresAdmin 4, I get a top 10. But when I want to test it on Spring via Postman on a endpoint, it keeps giving me 500 errors. It says ID is not found and/or should be in the group by or used in an aggregate function. I found in other topics I need to use 'distinct' or put ID in min/max(?). Still no success, and it's weirder that it does work in PostGreSQL itself.
I tried:
#Query( value = "select distinct keyword, sum (amount) as keyword_amount from search " +
"group by keyword order by keyword_amount DESC",
nativeQuery = true
)
List<Search> findTop10Keywords();
which give me the missing ID errors, and I tried without nativeQuery, but then I get:
search is not mapped [select distinct keyword, sum (amount) as keyword_amount from search group by keyword order by keyword_amount DESC
I'm not sure why/where search must be mapped?
SELECT keyword, sum(amount) AS keyword_amount
FROM "search" -- ?
GROUP BY keyword
ORDER BY keyword_amount DESC NULLS LAST
LIMIT 10;
Since you already GROUP BY keyword, adding distinct is an expensive no-op. Remove it.
sum(amount) might be NULL. If that can happen (depends on undisclosed details), be sure to use ORDER BY keyword_amount DESC NULLS LAST. See:
Sort by column ASC, but NULL values first?
Seems safe to assume that a query called indTop10Keywords should only return the top 10. So LIMIT 10.
"search" is a reserved word in standard SQL (even if allowed as identifier in Postgres). Maybe that's what throws off Spring. Double-quoting may help. But I would rather avoid reserved words as identifiers to begin with.

How to get result from two queries in same output window?

I need output from the below two queries simultaneously in one output window.
QUERY 1
SELECT C.SERVICENAME, C.SERVICEID , B.SOAPIN, B.SOAPOUT, A.TIMESTAMP
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_SOAPREQUESTS B, Schema1.CFG_SOAPSERVICES C
WHERE B.SERVICEID =C.SERVICEID AND
C.SERVICENAME <>'UploadAndPrepareDocumentEx1__sdweb_services_preload' AND
A.ID=B.LOGENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('02/01/2018 11:55:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('02/01/2018 12:03:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CGBXGVSG')));
Query 2
SELECT B.JSONIN, B.JSONOUT, A.TIMESTAMP, B.EVENT_MESSAGE, A.PROCESSID, A.status, A.SERVERNAME
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_EVENT B
WHERE B.EVENT_MESSAGE NOT IN ('getFileImage','submitBase64','loadDocumentToSign','getRefData') AND
A.ID=B.LOG_ENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('31/12/2017 13:43:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('31/12/2017 13:53:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CTHX8Y2G')));
Run with F5 - you'll get both queries' output in the script panel.
I talk about how this differs here
UNION might be one option, but you'll have to
uniform both column lists (i.e. they have to return the same number of columns which have to be of the same data type), which means that you'd have to add certain NULL columns to both queries
include additional identifier so that you'd know which SELECT returned which values
If you wanted to have them side-by-side, huh, that's not that easy. Thinking loudly: you'd have to have a column that joins those values. Those SELECTs would be inline views. You'd use an aggregate function (such as MAX) along with a DECODE (or CASE) to select values from both queries. Shortly: too much pain.
Now, why do you want to do that? What's wrong with two separate windows, placed side by side?
[EDIT] Showing example of how UNION might look like
select c.servicename, c.serviceid, b.soapin, b.soapout, a.timestamp, to_char(null), to_char(null), to_char(null) , to_number(null), to_char(null), to_char(null)
from ... the rest of your 1st query
union
select null , null , null , null , a.timestamp, b.jsonin , b.jsonout , b.event_message, a.processid , a.status , a.servername
from ... the rest of your 2nd query

Using TOP in ORACLE SQL 9

Hello I'am very new to writing SQL and I am trying to find the appropriate way to use TOP in Oracle SQl 9:
My example:
select * from example e, test t
where e.id = t.id
and country = 'USA'
order by state ASC;
What I am trying to do is take the bottom 20 % of my query but I know you cannot use TOP. After researching I still have not found an applicable answer. I know you have to first order them but am unsure of how to then take the bottom 20%(which would be TOP since the order is ASC)
In general (like if you want the top or bottom 17.2% of the rows) you can use row_number() and count() (analytic functions) to get the result.
20% is easier - you are looking for the top (or bottom) quintile. For this, you can use the ntile() function, like so:
select [column_names]
from (
select e.*, t.*, ntile(5) over (order by state) as nt
from ..... etc
)
where nt = 1;
The subquery is your query. The column_names in the outer query are whatever you actually need; you could also use select * but that will show the ntile too (which will be 1 in all rows).
If sorting something in ASCending order gives us the top set then surely sorting in DESCending order can give us the bottom set.
This solution uses the function NTILE() to divide the records into five buckets. The first bucket is the set we want (because sorted in descending order). Sorting in ascending order and taking the fifth quintile would have the same outcome.
select * from (
select e.*
, t.*
, ntile(5) over (order by state desc) nt
from example e, test t
where e.id = t.id
and country = 'USA'
)
where nt = 1
order by state desc
/
You don't say what your sort criteria are, so I've guessed.

How to make sort case insensitive while displaying the lower+upper case of values in the dropdown

I am trying to convert my query result to and order them according to lowercase in asc order. But while displaying I need to preserve all the original case (lower and upper case).
My query looks like this -
SELECT distinct (p.product_id) as product_id ,lcase(p.product_name) as product_name
from library TL, product p
WHERE TL.id = PL.id
AND pL.product_id = p.product_id
AND pL.product_id NOT IN (0)
order by lcase(product_name) asc;
But when I display it changes the entire dropdown values to lowercase. This is not what i want. I just want it to be displaying according to the order by lowercase.
How can I do it?
As far as I know, my orderby should have the same condition as the select isnt it?
How to make sort case insensitive while displaying the lower+upper case of values in the dropdown
You can try this,
SELECT product_id, product_name FROM (
SELECT distinct (p.product_id) as product_id ,(p.product_name) as product_name,
lcase(p.product_name) as pname
from unified.techlibrary TL, unified.techlibraryprod PL, unified.product p, unified.contenttype CT
WHERE TL.id = PL.id
AND pL.product_id = p.product_id
AND tl.contenttype_id in (1,3)
AND pL.product_id NOT IN (0)
) AS x order by x.pname
Hope it will help.

Selecting table in Oracle database in SPARQL

I using SPARQL query to get rows from table TRIPLES
"SELECT * WHERE { ?s ?p ?o }"
But I've got error that table or view doesn't exist. I think that it doesn't work because in this query no info about selecting tables. Am I right?
You're correct - you need to add a FROM clause, as in
SELECT * FROM TRIPLES WHERE ...
Share and enjoy

Resources