Get counts of values of an Enum in JQL - jpa

Is thare any way a JQL can get the counts according to the values of an Enum? For example, Enum has values as Single, Married, Divorced, etc. and get the counts of Persons Entity in a single Java Persistence Language Query?

There are two ways, either use a group by, or sub-selects in the Select clause,
Select Count(p), p.status from Person p group by p.status
or,
Select (Select Count(p) from Person p where p.status = Status.Single), (Select Count(p) from Person p where p.status = Status.Married), (Select Count(p) from Person p where p.status = Status.Divorced)
but sub-selects in the Select clause is not supported by JPA (at least JPA 2.0, 2.1 does I believe), EclipseLink 2.4 or greater does support this.

Related

How to add complex inner query to #Query annotaion

normal sql query which work correctly in db in sql developer passing values for bID and period.
SELECT * FROM A WHERE abcID IN (SELECT abcID FROM B WHERE bID=1) AND period=3
in project at Repository class I passed as this
#Query("select a from A where a.abcID IN:(select b.abcId from B where bID=:RevID) and period=:period")
error comes as
Space is not allowed after parameter prefix ':' [select a from A
where a.abcID IN:(select b.abcId from B where bID=:RevID) and
period=:period]
I want to know how should I insert above query correctly in #Query annotation
First of all I would tell you below points.
you can't use select query as select a from A where a.abcID. Here a is a column so can't define something like a.abcID. It need to be select column from tableA a where a.abcID
Same for query use in IN clause. It needs to be like select b.abcId from tableB b where b.bID=:RevID
What you use as :RevID, :period need to be passed as #Param("RevID"), #Param("period") to the query method.
This is the query template.
#Query("select a.nameOfcolumnYouWantToRetrieve from tableA a where a.someColumn in(select b.someColumn from tableB b where b.columnValueOfTableBYouwantToMatch=:RevID) and a.period=:period")
Using this points, try below query.
#Query("select a.id from A a where a.abcID in(select b.abcId from B b where b.bID =:RevID) and a.period=:period")

GROUP BY one column, then by another column

SELECT lkey, max(votecount) FROM VOTES
WHERE ekey = (SELECT ekey FROM Elections where electionid='NR2019')
GROUP BY lkey
ORDER BY lkey ASC
Is there an easy way to get the pkey in this Statement?
Solution should look like this
Use DISTINCT ON:
SELECT DISTINCT ON (v.ikey) v.*
FROM VOTES v
INNER JOIN Elections e ON e.ekey = v.ekey
WHERE e.electionid = 'NR2019'
ORDER BY v.ikey, v.votecount DESC;
In plain English, the above query says to return the single record for each ikey value having the highest vote count.

Can't solve this SQL query

I have a difficulty dealing with a SQL query. I use PostgreSQL.
The query says: Show the customers that have done at least an order that contains products from 3 different categories. The result will be 2 columns, CustomerID, and the amount of orders. I have written this code but I don't think it's correct.
select SalesOrderHeader.CustomerID,
count(SalesOrderHeader.SalesOrderID) AS amount_of_orders
from SalesOrderHeader
inner join SalesOrderDetail on
(SalesOrderHeader.SalesOrderID=SalesOrderDetail.SalesOrderID)
inner join Product on
(SalesOrderDetail.ProductID=Product.ProductID)
where SalesOrderDetail.SalesOrderDetailID in
(select DISTINCT count(ProductCategoryID)
from Product
group by ProductCategoryID
having count(DISTINCT ProductCategoryID)>=3)
group by SalesOrderHeader.CustomerID;
Here are the database tables needed for the query:
where SalesOrderDetail.SalesOrderDetailID in
(select DISTINCT count(ProductCategoryID)
Is never going to give you a result as an ID (SalesOrderDetailID) will never logically match a COUNT (count(ProductCategoryID)).
This should get you the output I think you want.
SELECT soh.CustomerID, COUNT(soh.SalesOrderID) AS amount_of_orders
FROM SalesOrderHeader soh
INNER JOIN SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
INNER JOIN Product p ON sod.ProductID = p.ProductID
HAVING COUNT(DISTINCT p.ProductCategoryID) >= 3
GROUP BY soh.CustomerID
Try this :
select CustomerID,count(*) as amount_of_order from
SalesOrder join
(
select SalesOrderID,count(distinct ProductCategoryID) CategoryCount
from SalesOrderDetail JOIN Product using (ProductId)
group by 1
) CatCount using (SalesOrderId)
group by 1
having bool_or(CategoryCount>=3) -- At least on CategoryCount>=3

Complex insert based on few subqueries

I have following tables:
Posts: id, CategoryId
PostAssociations: PostId FK Posts(id), AssociatedPostId FK Posts(id)
So each post may have many other posts as associated posts.
What I need is:
For each post P that does not have any associated posts yet, add 4 random associated posts from the same category (excluding post P - it should not be associated to himself).
So far I have
# SELECT Posts that don't have any associated posts yet
SELECT p.id
FROM "Posts" p
LEFT OUTER JOIN "PostAssociations" pa ON pa."PostId" = p.id
WHERE pa."PostId" IS NULL
And:
# SELECT 4 random posts from given category and excluding given id
SELECT id
FROM "Posts" p2
WHERE p2."CategoryId" = ? AND p2.id != ?
ORDER BY RANDOM()
LIMIT 4
I need query like this:
INSERT INTO "PostAssociations" VALUES ...
SQL fiddle with explanation what I need: http://sqlfiddle.com/#!2/6ba735/5
As you tagged the post with postgresql-9.3 I guess using LATERALto apply the random id generating query over all ids that are missing associations should work. (This should be functionally similar to using OUTER APPLYwith MS SQL for instance).
Sample SQL Fiddle (showing before, insert and after).
INSERT INTO PostAssociations
SELECT
p.id, rand.id rand
FROM Posts p
LEFT OUTER JOIN PostAssociations pa ON pa.PostId = p.id
LEFT JOIN LATERAL
(
SELECT id
FROM Posts
WHERE CategoryId = p.categoryid AND id != p.id
ORDER BY RANDOM()
LIMIT 4) AS rand ON TRUE
WHERE pa.PostId IS NULL;
I can't claim to be an expert with Postgresql so it's quite possible the query can be improved.

What's the best T-SQL syntax to filter for an ID that has a count of X or at least X or at most X in a joined table?

What's the best way to do something like this in T-SQL?
SELECT DISTINCT ID
FROM Members,
INNER JOIN Comments ON Members.MemberId = Comments.MemberId
WHERE COUNT(Comments.CommentId) > 100
Trying to get the members who have commented more than 100 times. This is obviously invalid code but what's the best way to write this?
This should get you what you're after. I'm not saying this is the absolutely best way of doing it, but it's unlikely you'll find anything better.
SELECT ID
FROM Members
INNER JOIN Comments
ON Members.MemberId = Comments.MemberId
GROUP BY ID
HAVING COUNT(*) > 100
I like using a subquery.
SELECT DISTINCT m.ID
FROM Members m
WHERE (SELECT COUNT(c.CommentID)
FROM Comments c
WHERE c.MemberID = m.MemberID) > 100
Try
SELECT ID
FROM Members
INNER JOIN (SELECT MemberID FROM Comments
GROUP BY MemberID HAVING COUNT(CommentId) > 100)
AS CommentCount ON Members.MemberID = CommentCount.CommentID