HQL and subqueries with joins - mysql

I've got the following sql query to retrieve the first row in each group ordered by date:
SELECT * FROM pls s1
INNER JOIN (
SELECT * FROM pls s2
ORDER BY s2.date DESC) a
ON (s1.id = a.id)
GROUP BY s1.name
Since joins with subqueries are not valid in HQL, how can it be modified?

Why not make that SQL statement a view?
create or replace view v_myview as
SELECT * FROM pls s1
INNER JOIN (
SELECT * FROM pls s2
ORDER BY s2.date DESC) a
ON (s1.id = a.id)
GROUP BY s1.name
Views can be mapped in the same manner as an entity, you just can't insert into them.

Related

Why does this query work with an alias but the one without does not?

When I remove the aliases and replace all the s1s with order_status_updates and all the s2s with orders I get nothing in return.
This one works
SELECT *
FROM order_status_updates AS s1
JOIN orders AS s2
WHERE s2.id = (SELECT MAX(s2.id) FROM orders)
AND s1.order_id = s2.id
AND s1.order_status_id = s2.order_status_id
This one does not
SELECT *
FROM order_status_updates
JOIN orders
WHERE orders.id = (SELECT MAX(orders.id) FROM orders)
AND order_status_updates.order_id = orders.id
AND order_status_updates.order_status_id = orders.order_status_id
First of all, don't JOIN using the WHERE clause but the ON clause:
SELECT *
FROM order_status_updates AS s1
JOIN orders AS s2
ON s1.order_id = s2.id AND s1.order_status_id = s2.order_status_id
WHERE s2.id = (SELECT MAX(s2.id) FROM orders);
Since s2.id in the WHERE clause refers to a single record, SELECT max(s2.id) FROM orders will result in s2.id. In other words, you can basically remove this condition.
The second query is different because here MAX(orders.id) refers to table orders mentioned in the FROM clause of the subquery. That is, SELECT MAX(orders.id) FROM orders will return the largest order ID.

Sub Query Not IN With Left Join Alternative?

I have Query Like This
SELECT f.ACCOUNT_ID,
f.TGL,
p.ACCOUNT_EMAILADDRESS
FROM distributor_kokola.forecast f
inner join distributor_kokola.push_distributor p on p.ACCOUNT_ID = f.ACCOUNT_ID
where f.ACCOUNT_ID NOT IN(
select ACCOUNT_ID
from distributor_kokola.forecast
where DATE_FORMAT(TGL, "%Y-%m") = DATE_FORMAT(CURDATE(), "%Y-%m")
group by ACCOUNT_ID
)
group by f.ACCOUNT_ID;
That Sub Query work but To Slow so I change it with Left Join, it work faster
SELECT f.ACCOUNT_ID,
f.TGL,
p.ACCOUNT_EMAILADDRESS
FROM distributor_kokola.forecast f
left join(
select ACCOUNT_ID
from distributor_kokola.forecast
where DATE_FORMAT(TGL, "%Y-%m") = DATE_FORMAT(CURDATE(), "%Y-%m")
group by ACCOUNT_ID
)subb on subb.ACCOUNT_ID = f.ACCOUNT_ID
inner join distributor_kokola.push_distributor p on p.ACCOUNT_ID = f.ACCOUNT_ID
group by f.ACCOUNT_ID;
But, My issue is Still Contain wrong Result,
With Not IN, query 1 select where NOT IN query 2.
How can I get like NOT IN query with left join.
Can Anyone Help Me?
thanks.
You have to add a WHERE clause to filter by the results of your LEFT JOIN. If you add an appropriate WHERE clause WHERE subb.ACCOUNT_ID IS NULL, it should work as expected (since you used a GROUP BY in your subquery, there's no danger of duplicate rows):
SELECT f.ACCOUNT_ID,
f.TGL,
p.ACCOUNT_EMAILADDRESS
FROM distributor_kokola.forecast f
left join(
select ACCOUNT_ID
from distributor_kokola.forecast
where DATE_FORMAT(TGL, "%Y-%m") = DATE_FORMAT(CURDATE(), "%Y-%m")
group by ACCOUNT_ID
) subb on subb.ACCOUNT_ID = f.ACCOUNT_ID
inner join distributor_kokola.push_distributor p on p.ACCOUNT_ID = f.ACCOUNT_ID
WHERE sub.ACCOUNT_ID IS NULL
group by f.ACCOUNT_ID;
Update
The goal of our LEFT JOIN is to find all rows in our forecast table that don't have a matching row in the subquery. Therefore, we need a WHERE clause that removes all rows with a matching row - WHERE sub.ACCOUNT_ID IS NULL fits quite nicely.
SO user #quassnoi has written a wonderful comparison of different methods to achieve this goal.

Regarding group by inside inner join mysql

I am trying the below group by inside inner join in mysql. It's saying unknown column name. Could You please help me out regarding this. I am getting an error on this query "SELECT Min(Id) FROM testinbcalls group by lc.DBID" in the inner join saying "Unknown column name DBID in the groupby). Is there an alternative way I can modify this query if groupby is not allowed. I tried ""SELECT Min(Id) FROM testinbcalls WHERE Id= lc.DBID" instead of group by but it didn't work. I prefer not move the check to the where clause as i want the records to be filtered on the inner join itself. Could anyone help me out. Thanks
SELECT DISTINCT ic.Id as `Id`, lc.DBID,
init.Name as Init,
lc.TargetNumber as PhoneNumber,
CONCAT(us.FirstName,' ',us.Surname) as UserName,
iout.Name as Outc FROM
testcalls ic
INNER JOIN testinit init on ic.InitId=init.Id
INNER JOIN users us on ic.UserId=us.Id
INNER JOIN testinbcalls lc ON ic.Id=lc.CallId AND lc.DBID IS NOT NULL AND ic.Id=(**SELECT Min(Id) FROM testinbcalls group by lc.DBID** )
INNER JOIN (SELECT MIN(Id) Id FROM testinbcalls group by lc.DBID) mincallid ON ic.Id=mincallid.Id
INNER JOIN icomes iout on ic.OutId=iout.Id
WHERE ic.AssignedDateTime between '2015-06-08 00:00:00' and '2015-06-09 23:59:59' ORDER BY Id DESC limit 250;
You change it to below removing the table alias lc. With that you are actually referring the outer query table.
INNER JOIN (SELECT MIN(Id) AS MinId FROM testinbcalls group by DBID)

Using JOINs and group by together in single sql query

I'm not able to use JOINS and group-by together:
I searched for this...but I didn't find the solution..Problem is as below:
I have two tables, first is main_table with fields eid, name, status
Second table is followups with fields fid, eid, last_date, remarks, and next_date
Second table is used to store followup details of clients (client details stored in main_table) and i want to get last followup record for each client with selected date period (from_date to to_date) and sort by next_date in descending order.
i used the below query but not working
SELECT *
FROM main_table as MT
JOIN followups as MF on MT.eid=MF.eid
WHERE MT.status='open' AND MF.NDate<='2012-12-07'
GROUP BY MF.eid
ORDER BY MF.next_date DESC
thanks in advance...guys
Try This
SELECT * FROM main_table AS MT
LEFT JOIN (SELECT * FROM (SELECT * FROM followups ORDER BY next_date DESC) AS A GROUP BY eid) AS MF ON MT.eid=MF.eid
WHERE MT.status='open'
AND MF.NDate<='2012-12-07';
You can try something like this:
select m.eid,
m.name,
m.status,
f1.last_date,
f1.remarks,
f1.next_date
from maintable m
left join
(
select max(last_date) maxLast, eid
from followups
where last_date between from_date and to_date
group by eid
) f
on m.eid = f.eid
left join followups f1
on f.maxLast = f1.last_date
and f.eid = f1.eid
where m.status='open'
and f1.next_date<='2012-12-07'
order by f1.next_date desc
Try this:
SELECT * FROM main_table AS MT
LEFT JOIN (SELECT * FROM (SELECT * FROM followups WHERE NDate<='2012-12-07' ORDER BY next_date DESC) AS A GROUP BY eid) AS MF ON MT.eid=MF.eid
WHERE MT.status='open';

How to rewrite SQL query that has subquery with joins

I have a SQL query that has a subquery that has joins. I would like to rewrite the query without the subquery so that I can create a view. MySQL does not allow SELECT statements where the FROM is a subquery.
Is this possible? I've tried removing the outer select and moving the group by inside the subs query. This partially works but some of the data is incorrect.
select *
from (SELECT r.id, r.dateAdded, r.listingId, r.rating, r.username, r.valid, tbl_data.nameShort, tbl_data.desk, d.model, d.hardware, d.serial, l.appVersion, r.photoUrl, r.comment
FROM tbl_ratings r
JOIN tbl_data on r.listingId = vi_data.id
JOIN tbl_devices d on r.serial = d.serial
JOIN tbl_log l on l.serial = d.serial
ORDER BY d.serial, l.dateAdded DESC) x
group by id
order by dateAdded DESC
Thanks in advance!
Is it as simple as:
SELECT r.id, r.dateAdded, r.listingId, r.rating, r.username, r.valid,
tbl_data.nameShort, tbl_data.desk, d.model, d.hardware,
d.serial, l.appVersion, r.photoUrl, r.comment
FROM tbl_ratings r
JOIN tbl_data on r.listingId = vi_data.id
JOIN tbl_devices d on r.serial = d.serial
JOIN tbl_log l on l.serial = d.serial
GROUP BY r.id
ORDER BY r.dateAdded DESC
Also, you have a reference to "vi_data" that isn't anywhere else in the query
Change your group by clause to be group by r.id. Since you're selecting from a derived table (the subquery), the db can't tell that there's only one "id" field in that derived table - it only sees the column headers as specified in the subquery, which is r.id.