SQL Azure and JAVA do not want to run query - java

I have the following statement in JAVA:
String query = "SELECT H.Name as Name, R.RacesWon as Race FROM Horses AS H, Conditions AS C, Races AS R"+ "WHERE H.ID = R.HorseID AND C.ID = R.ConditionID";
I have connection to a SQL Azure database with 3 tables Horses, Conditions and Races.
I just made this join and I've got this exception:
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near 'H'.
I do not know why and I have tried every possibility with Horses, Races and Conditions instead of H,C,R with AS , without AS without success.
Furthermore I have run :
String query = "SELECT Name FROM Horses WHERE ID = 1";
and was OK.
Any suggestions?

You have some concatenation issues. As #lrb notes in the comments:
R"+ "WHERE
Would equal RWHERE which would cause an error.
Also use SQL92 syntax instead of SQL89 with inner join
Instead try:
String query = "SELECT
H.Name as Name,
R.RacesWon as Race
FROM Conditions as C
inner join Races AS R on C.ID = R.ConditionID
inner join Horses AS H on R.HorseID = H.ID";

Related

How can I count a subquery with group by

I'm new here, I'm french, apologize my English please.
I have a grid with a HQL source.
The first HQL's query send the count of records, and the second query the data.
But the result of the first query isn't equal to the number of record of the second query.
The first query (return 26 records) :
SELECT
resou.res_book.res_book_id as record,
strset.str_set_cd as room,
concat(coalesce(person.firstname, ' '), ' ', coalesce(person.lastname, ' ')) as name,
prod_h.d_from_d as start_date,
prod_h.d_to_d as end_date,
(SUM(prod_h.amt_total_ivat) - SUM(pay_l.amt_paymt)) as total
FROM Com_site as site
inner join site.com_bu as bu
inner join bu.com_activ as activ
inner join activ.inv_head as head
inner join head.inv_person as person
inner join person.res_rooming as rooming
inner join rooming.res_resou as resou
inner join resou.str_set as strset
inner join person.inv_prod_h as prod_h
inner join head.inv_pay_l as pay_l
inner join prod_h.pdt_prod as prod
WHERE
head.tp_folio_tp = 0 and
prod_h.d_to_d <= '2020-07-01' and
site.com_site_id = 1 and
prod_h.inv_accou_itm.inv_accou_itm_id is null and
prod.b_rent_bl = false and
'2020-07-01' between resou.d_from_d and resou.d_to_d
GROUP BY
head.inv_head_id
, person.firstname
, person.lastname
, strset.str_set_cd
, resou.res_book.res_book_id
, prod_h.d_from_d
, prod_h.d_to_d
, head.tp_folio_tp
, prod.pdt_prod_id
And the second query (return 1 record but the value is 316 (not 26)) :
select
(
SELECT
COUNT(head.inv_head_id) as counted
from site.com_bu as bu
inner join bu.com_activ as activ
inner join activ.inv_head as head
inner join head.inv_person as person
inner join person.res_rooming as rooming
inner join rooming.res_resou as resou
inner join resou.str_set as strset
inner join person.inv_prod_h as prod_h
inner join head.inv_pay_l as pay_l
inner join prod_h.pdt_prod as prod
WHERE
head.tp_folio_tp = 0 and
prod_h.d_to_d <= '2020-07-01' and
site.com_site_id = 1 and
prod_h.inv_accou_itm.inv_accou_itm_id is null and
prod.b_rent_bl = false and
'2020-07-01' between resou.d_from_d and resou.d_to_d
) as counted
from Com_site as site
I tried:
COUNT(COUNT(head.inv_head_id)), COUNT(*the subquery here*)
but nothing works...
Anyone can please help me ?
Thank's you in advance.
I don't quite understand why you want to determine the count first and then query all the data, you could just determine the count by counting the amount of fetched entities, so there is no need for a second query.
In case you are trying to implement pagination, I can recommend you take a look at Blaze-Persistence which has excellent support for creating efficient count queries from a base query and bounded counting, but also supports various paginations techniques: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination
Thank you for helping me ! I found that my query is tottaly wrong, so I rewrote the query without group by, and it's works ! The first query send the correct count of record of the second query.

SQL: Get a limit of records per entity

I have the following setup (Java/Hibernate/PostgreSQL):
TeamName {
id: Long;
name: String;
team: Team;
....
}
Series {
id: Long;
season: Season;
dateScheduled: Date;
}
SeriesTeam {
id: Long;
series: Series;
team: TeamName;
}
SeriesTeam {
id: Long;
team: TeamName;
}
What I want to do is do a select of the past n series (say 10) or the next series from the current date. Here's what I have so far:
select s.* from series s
inner join series_teams st on st.series_id = s.id
inner join team_names tn on tn.id = st.team_name_id
where tn.id in (:teamIds) and s.date_scheduled < CURRENT_DATE
order by s.date_scheduled desc
But that is going to get me all the prior series for all teams and I will have to use Java to pick out what I want How would I go about doing what I want? Thanks!
EDIT: For example, say I wanted a limit of 10 per team name, and there are 24 teams, I would want max of 240 records returned to me. (assuming 10 exist before current date)
EDIT2: Here is the code that I want for a single team:
select s. from series s
inner join series_teams st on st.series_id = s.id
where st.team_name_id=85 and s.date_scheduled < CURRENT_DATE
order by s.date_scheduled desc
limit 10
I just need to be able to apply this for all the teams....I don't want to make x SQL calls for every team.
I think this will work. The syntax is in mysql and you can try it at that site the structure they have is similar to yours. you can adjust the limit value to change how many from each employee to return sorted by date. Probably add the current date check there too i guess.
Basically I joined all the needed tables together then created a new column that will tell me if that row is one we should return then added that check in the where clause.
https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in
SELECT e.employeeid, lastname,orderdate, orderdate in (select orderdate from
orders ord where e.employeeid=ord.employeeid order by orderdate limit 2) as
good FROM Employees as e join orders as o on e.employeeid=o.employeeid where
good=1 order by e.employeeid, o.orderdate;
for your case:
select s.id, s.season_id, s.date_scheduled, st.team_name_id,
s.date_scheduled in (
select s2.date_scheduled from series s2
inner join series_teams st2 on st2.series_id = s2.id
inner join team_names tn2 on tn2.id = st2.team_name_id
where tn.id =tn2.id and s2.date_scheduled < CURRENT_DATE
order by s.date_scheduled desc limit 5
) as foo
from series s
inner join series_teams st on st.series_id = s.id
inner join team_names tn on tn.id = st.team_name_id
where tn.id in (:teamIds) and foo = true
order by st.team_name_id, s.date_scheduled desc

How to query for number of records in select with "group by" clause in JPA/EclipseLink?

Suppose you have a following JPA query:
select car.year, car.month, count(car) from Car car group by car.year, car.month
Before we query for results, we need to know how many records this query will return (for pagination, UI and so on). In other words we need something like this:
select count(*) from
(select car.year, car.month, count(car)
from Car car group by car.year)
But JPA/EclipseLink does not support subqueries in "from" clause. It there a way around it?
(Of course you can use plain SQL and native queries, but this is not an option for us)
A portable JPA solution:
select count(*) from Car c where c.id in
(select MIN(car.id) from Car car group by car.year, car.month)
You could also go with something like:
select COUNT(DISTINCT CONCAT(car.year, "#", car.month)) from car
but I expect this to be less performant due to operations with textual values.
What about:
select count(distinct car.year) from car
I have another approach to solve this issue . by using my approach you don't need to know the no of rows this query is going to return.
here it is your solution :-
you going to need two variables
1) pageNo (your page no should be 1 for first request to data base and proceeding request it should be incremental like 2 ,3 , 4 5 ).
2) pageSize.
int start = 0;
if(pageNo!=null && pageSize!=null){
start = (pageNo-1) * pageSize;
}else{
pageSize = StaticVariable.MAX_PAGE_SIZE; // default page size if page no and page size are missing
}
your query
em.createquery("your query ")
.setfirstResult(start)
.setMaxResult(pageSize)
.getResultList();
As #chris pointed out EclipseLink supports subqueries. But the subquery can't be the first one in the from-clause.
So I came up with the following workaround which is working:
select count(1) from Dual dual,
(select car.year, car.month, count(car)
from Car car group by car.year) data
count(1) is important as count(data) would not work
You have to add an entity Dual (If your database does not have a DUAL table, create one with just one record.)
This works but I still consider it a workaround that would only work if you allowed to create the DUAL table.
Simply you can use setFirstResult and setMaxResult to set record bound for query ,also use size of list to return count of records that query runs. like this :
Query query = em.createQuery("SELECT d.name, COUNT(t) FROM Department d JOIN
d.teachers t GROUP BY d.name");
//query.setFirstResult(5);
//query.setMaxResult(15); this will return 10 (from 5 to 15) record after query executed.
List<Object[]> results = query.getResultList();
for (int i = 0; i < results.size(); i++) {
Object[] arr = results.get(i);
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[j] + " ");
}
System.out.println();
}
-----Updated Section------
JPA does not support sub-selects in the FROM clause but EclipseLink 2.4 current milestones builds does have this support.
See, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Sub-selects_in_FROM_clause
You can probably rewrite the query with just normal joins though.
Maybe,
Select a, size(a.bs) from A a
or
Select a, count(b) from A a join a.bs b group by a
I hope this helps you.

Make one query out of two others?

I have never been very good at SQL queries (I've always preferred NoSQL databases, but I need to use a SQL database this time).
I need to research how many seats are sold compared to the amount of total seats in cinema halls. At the moment I can accomplish this using 2 different queries in Hibernate, one for the total amount of seats and the other for the amount of sold seats, and then divising these results.
This is my code :
Double amountOfSoldTickets = ((Long) session.createQuery("select count(*) from Ticket t where t.vertoning.zaal.cinemacomplex.id = :id").
setInteger("id", complex.getId()).list().get(0)).doubleValue();
Double capacity= ((Long) session.createQuery("select sum(z.capaciteit) from Zaal z").list().get(0)).doubleValue();
return amountOfSoldTickets / capacity;
I thought about using a subquery though I have no idea how to do this in hibernate.
If anyone has any idea how to solve this in one query it'd be greatly appreciated.
Some additional info: I let hibernate implicitly join my tables in the first query.
Ticket has a many to one to Vertoning, Vertoning has a many to one to Zaal, Zaal has a many to one to cinemacomplex
I encourage you to learn SQL -- and to learn it on a real database instead of through the HQL interface. HQL is useful for what it does, but it misses on some very important SQL functionality.
I believe the following will work in HQL:
select count(*) as SoldSeats,
(select sum(z.capaciteit) from Zaal z) as Capacity
from Ticket t
where t.vertoning.zaal.cinemacomplex.id = :id;
In just MySQL, you could put these as subqueries in the from clause:
select t.SoldSeats, z.Capacity
from (select count(*) as SoldSeats,
from Ticket t
where t.vertoning.zaal.cinemacomplex.id = :id
) t
(select sum(z.capaciteit) as Capacity
from Zaal z
) z;
Note that if this is inside a loop where you are assigning different values to id, then the whole loop can possibly replaced with SQL.
I suggest you run this query:
Long[] amountOfSoldTicketsToCapacity =
((Long[]) session.createQuery(
"select count(*), z.capaciteit, z.id " +
"from Ticket t " +
"inner join t.vertoning v " +
"inner join v.zaal z " +
"inner join z.cinemacomplex c " +
"where c.id = :id " +
"group by z.capaciteit, z.id "
)
.setInteger("id", complex.getId())
.uniqueResult());
if {
throw new IllegalArgumentException("There are no tickets sold for Zaal#" + complex.getId());
}
double capacity = (amountOfSoldTicketsToCapacity.length != 0) ?
((double) amountOfSoldTicketsToCapacity[0]) / amountOfSoldTicketsToCapacity[1] : 0D;
Doing the division in Java is simpler, as in SQL you'd probably have to CAST one operand to NUMERIC.

Converting SQL with subselect in select to HQL

I have the following SQL that I am having problems converting to HQL. A NPE is getting thrown -- which I think has something to do with the SUM function. Also, I'd like to sort on the subselect alias -- is this possible?
SQL (subselect):
SELECT q.title, q.author_id,
(SELECT IFNULL(SUM(IF(vote_up=true,1,-1)), 0)
FROM vote WHERE question_id = q.id) AS votecount
FROM question q ORDER BY votecount DESC
HQL (not working)
SELECT q,
(SELECT COALESCE(SUM(IF(v.voteUp=true,1,-1)), 0)
FROM Vote v WHERE v.question = q) AS votecount
FROM Question AS q
LEFT JOIN q.author u
LEFT JOIN u.blockedUsers ub
WHERE q.dateCreated BETWEEN :week AND :now
AND u.id NOT IN (
SELECT ub.blocked FROM UserBlock AS ub WHERE ub.blocker = :loggedInUser
)
AND (u.blockedUsers IS EMPTY OR ub.blocked != :loggedInUser)
ORDER BY votecount DESC
Here is the working HQL if anyone is interested:
SELECT q,
(SELECT COALESCE(SUM(CASE v.voteUp WHEN true THEN 1 ELSE -1 END), 0)
FROM Vote v WHERE v.question = q) AS votecount
FROM Question AS q
LEFT JOIN q.author u
LEFT JOIN u.blockedUsers ub
WHERE q.dateCreated BETWEEN :week AND :now
AND u.id NOT IN (
SELECT ub.blocked FROM UserBlock AS ub WHERE ub.blocker =:loggedInUser
)
AND (u.blockedUsers IS EMPTY OR ub.blocked !=:loggedInUser)
ORDER BY col_1_0_ DESC
Notice the ORDER BY col_1_0_
There is an open issue with Hibernate -- it does not correctly parse aliases and since the aliases are renamed in the query, an error will be thrown. So, col_1_0_ is basically a workaround --it's the name Hibernate generates.
See issue:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-892

Categories