I have the following query:
SELECT ?tag WHERE {
?r ns9:taggedWithTag ?tagresource.
?tagresource ns9:name ?tag
}
LIMIT 5000
and the results are:
abc
abc
abc
abc
abc
abc
abc
abd
ads
anb
I want to get somthing like:
tag | count
-----------------
abc 7
abd 1
ads 1
anb 1
I have tried it with count(*) and count(?tag), but than I get the error message "Variable or "*" expected." Can someone tell me, how to make it right?
If you're using Java and Jena's ARQ, you can use ARQ's extensions for aggregates. Your query would look something like:
SELECT ?tag (count(distinct ?tag) as ?count)
WHERE {
?r ns9:taggedWithTag ?tagresource.
?tagresource ns9:name ?tag
}
LIMIT 5000
The original SPARQL specification from 2008 didn't include aggregates, but the current version, 1.1, from 2013 does.
Using COUNT(), MIN(), MAX(), SUM(), AVG() with GROUP BY can produce summary values for groups of triples. Note, these patterns might be specific to SPARQL 1.1.
For example, this one can sum the ?value for each ?category,
SELECT ?category (SUM(?value) as ?valueSum)
WHERE
{
?s ?category ?value .
}
GROUP BY ?category
This one can count the number of uses for predicate ?p,
SELECT ?p (COUNT(?p) as ?pCount)
WHERE
{
?s ?p ?o .
}
GROUP BY ?p
These examples are inspired by material from Bob DuCharme (2011), "Learning SPARQL". O’Reilly Media, Sebastopol, CA, USA; see http://www.learningsparql.com/
To avoid the error "Bad aggregate" upon using GROUP BY:
The grouping variables should match ; (?category in the first example)
The rest of the variables in the SELECT should each result into one value ; (SUM(?value) as ?valueSum) in the first example.
Related
(Using Oracle 11.2)
I have a rather complicated SQL with something like
wm_concat( distinct abc )
that is expected to return some varchar2(4000) compatible result.
It causes ORA-00932: inconsistent datatypes in my select used in some coalesce( some_varchar_col, wm_concat( ... ) ).
So I tried casting it via two different methods:
dbms_lob.substr( ..., 4000 ) -- L) tried even with 3000 in case of "unicode byte blow-up"
cast( ... as varchar2(4000)) -- C) tried even with 3000 in case of "unicode byte blow-up"
(The are used in a view, but playing around with it suggests, it is not related to the views)
Depending on the column and other operators I either get N) no result or O) ORA-22922:
select * from view_with_above_included where rownum <= 100
N) My Eclipse Data Explorer JDBC connection returns without any result (no columns without results, no (0 rows effected), only the query time statistics). (It could be an internal exception not treated as such?)
O)
ORA-22922: nonexistent LOB value
ORA-06512: in "SYS.DBMS_LOB", line 1092
ORA-06512: in line 1
Strangely the following test queries work:
-- rownum <= 100 would already cause the above problems
select * from view_with_above_included where rownum <= 10
or
select * from view_with_above_included
but looking at the actual aggregated data does not show aggregated data that would exceed 1000 characters in length.
Luckily, it works with the listagg( ... ) function provided since 11.2 (we are already running on), so we did not have to investigate further:
listagg( abc, ',' ) within group ( order by abc )
(Where wm_concat(...) is, as one should know, some internal and officially unsupported function.)
a rather nice solution (because it is not so bloated) to implement the distinct functionality is via self-referencing regexp functionality which should work in many cases:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )
(Maybe/Hopefully we will see some working listagg( distinct abc ) functionality in the future, which would be very neat and cool like the wm_concat syntax. E.g. this is no problem since a long time with Postgres' string_agg( distinct abc )1 )
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
If the list exceeds 4000 characters, one cannot use listagg anymore (ORA-22922 again).
But luckily we can use the xmlagg function here (as mentioned here).
If you want to realize a distinct on a 4000-chars-truncated result here, you could outcomment the (1)-marked lines.
-- in smallercase everything that could/should be special for your query
-- comment in (1) to realize a distinct on a 4000 chars truncated result
WITH cfg AS (
SELECT
',' AS list_delim,
'([^,]+)(,\1)*(,|$)' AS list_dist_match, -- regexp match for distinct functionality
'\1\3' AS LIST_DIST_REPL -- regexp replace for distinct functionality
FROM DUAL
)
SELECT
--REGEXP_REPLACE( DBMS_LOB.SUBSTR( -- (1)
RTRIM( XMLAGG( XMLELEMENT( E, mycol, listdelim ).EXTRACT('//text()')
ORDER BY mycol ).GetClobVal(), LIST_DELIM )
--, 4000 ), LIST_DIST_MATCH, LIST_DIST_REPL ) -- (1)
AS mylist
FROM mytab, CFG
To see if there is a Todd in my database I currently do the following:
SELECT * FROM MyTable WHERE name='Todd' LIMIT 1
I then check the Cursor to see if its size == 1. Is there a way to return a 0 or 1 from the select statement if the condition is false or true, rather than a list of fields?
You can do
SELECT COUNT(*) it_exists
FROM
(
SELECT 1
FROM MyTable
WHERE name = 'Todd'
LIMIT 1
) q;
An inner select guarantees that LIMIT is applied. Meaning if you have hypothetically thousands of matching rows database engine will stop and return results after the first one instead of going through all of them.
Output
| it_exists |
|-----------|
| 1 |
Here is SQLFiddle demo
I'm struggling with maybe a simple query but I'm unable to find an answer :
Let's give the following simple schema :
Nodes :
Package1
Library1
Library2
Library3
Relationships:
(Library1)-[:USES {in_version:'1.1'}]->(Package1)
(Library2)-[:USES {in_version:'1.2'}]->(Package1)
(Library3)-[:USES {in_version:'1.2'}]->(Package1)
Simple no ?
So what I would like is to return my package node, and group relationships by distinct in_version property and the number of times the in_version is used
This should be the return I would like to have :
package | in_version | usage |
Package 1 | 1.1 | 1 |
Package 1 | 1.2 | 2 |
I tried to combine distinct, collect, ..but I'm struggling currently
Edit
My last query is as follow :
MATCH (p:Package)<-[r:USES]-()
WHERE p.name = 'Package1'
WITH p, collect(r) as v
UNWIND v as x
RETURN distinct x.in_version, count(x) as usage
ORDER BY usage DESC
And I can get the versions and the usage correctly.
But if I want to add the package name to the return, cypher complain about the '.' in x.in_version
MATCH (p:Package)<-[r:USES]-()
WHERE p.name = 'Package1'
WITH p, collect(r) as v
UNWIND v as x
RETURN p.name, distinct x.in_version, count(x) as usage
ORDER BY usage DESC
While the p.name is not necessary for this query as I know it in advance, the goal is to 1st filter packages having the most uses relations and then return this query by package in one time
Thanks in advance
Chris
Try this query
match (lib)-[r:USES]->(pack)
where has(r.in_version)
with pack, collect(r.in_version) as vers,lib
with pack,vers ,collect(lib) as libs,count(lib) as usage
return pack as package,vers as in_version,usage
The question probably is quite confusing.
In affect i have the following:
WatchList table
UserId | FilmId
| 3 77
| etc etc
|
|
|
these are foreign keys for the following tables
FilmDB - Film_title, Film_plot, Film_Id etc.
and
aspnet_memberships - UserId, Username etc..
Now, i presume i will need to use a join but i am struggling with the syntax.
I would like to use 'Count' on the 'WatchList' and return the most frequent filmId's and their counterpart information, but i'd then like to return the REST of the FilmDB results, essentially giving me a list of ALL films, but with those found in the WatchedList my frequently sorted to the top.
Does that make sense? Thanks.
SELECT *
FROM filmdb
LEFT JOIN (
SELECT filmid, count(*) AS cnt
FROM watch_list
GROUP BY filmid) AS a
ON filmdb.film_id = a.filmid
ORDER BY isnull(cnt, 0) DESC;
http://sqlfiddle.com/#!3/46b16/10
You did not specify if the query should be grouped by film_id or user_id. The example I have provided is grouped by user if you change that to film_id then you will get the watch count for all users per film.
You need to use a subquery to get the count and then order the results by the count descending to get an ordered list.
SELECT
*
FROM
(
SELECT
WatchList.Film_Id,
WatchCount=COUNT(*)
FilmDB.Film_Title
FROM
WatchList
INNER JOIN FilmDB ON FilmDB.Film_Id=WatchList.Film_Id
GROUP BY
WatchList.UserID,
WatchList.Film_Id,
FilmDB.Film_Title
)AS X
ORDER BY
WatchCount DESC
I am using Oracle 11G sql and I want to calculate the Total_price which which means quantity*unit_price. How to do that by creating function for the columun
Total_price?
Because Experts are there and they can help me.
here is my table attributes with their corresponding data
Table: ITEM
item_id item_name quantity unit_price Total_price
-------------------------------------------------------------
1001 soap 5 $10
1002 Omo 2 $15
1003 Perfume 1 $52
1004 Socks 3 $7
1005 Tooth Brush 2 $5
I tried this:
CREATE OR REPLACE FUNCTION total_ammount_fn
RETURN number (10,2);
IS
Total_amount number(10,2);
BEGIN
SELECT Quantity, Rate_per_unit, Total_amount
FROM purchase;
Total_amount=Quantity*Rate_per_unit;
RETURN Total_amount;
END;
/
finally:
Warning: Function is created with compilation errors.
As you are using 11g will suggest that you declare Total Price as a Virtual Column in your table ITEM. You can use the below syntax for column
Total_Price NUMBER(10,2) GENERATED ALWAYS AS (quantity*unit_price)
You can get more details of the Virtual Functions here
If you want to do it with a PL/SQL construct, then suggest that you use a procedure, it should be like :
CREATE OR REPLACE procedure total_ammount_p
IS
Begin
Update item set total_price = unit_price*quantity;
commit;
END;
/
Of the two, it will be better to use Virtual Column based approach
Hope is Helps
Vishad