How to rewrite SQL query that has subquery with joins - mysql

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.

Related

SQL query gets stuck if adding ORDER BY

I am working with a query, which looks like this
SELECT s.c1, s.t, s.u, s.dt, t.temp, t.dt AS dt2
FROM `systemusage` AS s
INNER JOIN temperature AS t ON s.did=t.did
WHERE t.did = (SELECT id FROM devices WHERE m = 1)
LIMIT 1
Which works just fine, however if I add ORDER BY s.id, then the query gets totally stuck, can someone guide me on why? the id field is primary, so it should be indexed no?
Add an index on the column temperature.did so that the WHERE clause can be implemented efficiently.
It also may help to replace WHERE t.did = (SELECT ...) with a JOIN.
SELECT s.c1, s.t, s.u, t.temp
FROM `systemusage` AS s
INNER JOIN temperature AS t ON s.did=t.did
INNER JOIN devices AS d ON d.id = t.did
WHERE d.m = 1
ORDER BY s.id DESC, t.id DESC
LIMIT 1

MySql Query: Getting a record count within query

I got my query working but it doesn't count the rows... in my left outer join.
SELECT mUserId,mUserName,COALESCE(x.likeId,0) AS likeCount
FROM likes
LEFT JOIN members ON likes.likeMember = members.mUserId
LEFT OUTER JOIN (SELECT likeId, count(*) n FROM likes WHERE likeMember = likes.likeMember) x ON likes.likeMember = x.likeId
WHERE likeDate > '2014-11-16 07:44:47'
GROUP BY likeMember
ORDER BY `likeCount` DESC
Any suggestions?
This is your query:
SELECT mUserId,mUserName,COALESCE(x.likeId,0) AS likeCount
FROM likes LEFT JOIN
members
ON likes.likeMember = members.mUserId LEFT OUTER JOIN
(SELECT likeId, count(*) n
FROM likes
WHERE likeMember = likes.likeMember
) x
ON likes.likeMember = x.likeId
WHERE likeDate > '2014-11-16 07:44:47'
GROUP BY likeMember
ORDER BY `likeCount` DESC;
It is a bit absurd. Either do an aggregation in the subquery. Or do an aggregation in the outer query. But not both. I suspect you want something more like this:
SELECT m.mUserId, m.mUserName, COUNT(*) AS likeCount
FROM likes l LEFT JOIN
members m
ON l.likeMember = m.likeId
WHERE l.likeDate > '2014-11-16 07:44:47'
GROUP BY l.likeMember
ORDER BY `likeCount` DESC;
The problem with your subquery is the WHERE clause. You think it is correlated to the outer query. But it is really interpreted as:
WHERE likes.likeMember = likes.likeMember
In other words, the condition is true whenever likes.likeMember is not NULL.

Mysql Nested/Multiple Query handling

I have three queries gives me result individually correct but my requirement is i need all result in single query only so how should i proceed?
select * from user_post_like
inner join user_post on user_post_like.postID = user_post.postID
inner join Users on Users.userID=user_post_like.userID
where (user_post.poster='$uid' AND user_post_like.userID!='$uid')
ORDER BY likeID DESC;
select * from user_post_comment
inner join user_post on user_post_comment.postID = user_post.postID
inner join Users on Users.userID=user_post_comment.commenter
where (user_post.poster='$uid' AND user_post_comment.commenter!='$uid')
ORDER BY commentID DESC;
select * from user_post_share
inner join user_post on user_post_share.postID = user_post.postID
inner join Users on Users.userID=user_post_share.Share_user_id
where (user_post.poster='$uid' AND user_post_share.Share_user_id!='$uid')
ORDER BY shareID DESC;
Since you're joining the tables anyway, you can put columns from all in your select - and keep your statement readable. If you have duplicate column names (from different tables) you may need to aggregate them with functions and group by.
SELECT s.*, p.*, u.*
FROM user_post_share s
INNER JOIN user_post p ON s.postID = p.postID
INNER JOIN Users u ON u.userID = p.poster
WHERE (p.poster='$uid' AND s.Share_user_id != '$uid')
ORDER BY shareID DESC
try sumthing like this
select * from user_post_like,user_post_comment,user_post_share <inner joins> <where conditions>

HQL and subqueries with joins

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.

MySQL select in join clause scanning too many rows

Oke guys, the following has been bugging me all day:
I use the query below to select an overview of products and prices including the latest result-price based on field StartTime from another table (tresults). To do this I thought I would need a subselect in the join.
The problem is that the EXPLAIN function is telling me that MySQL is scanning ALL result rows (225000 rows) not using any index.
Is there some way I can speed this up? Preferably by adding a WHERE statement to have mysql look only at the rows with the corresponding pID's.
select p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice, min(price), min(price)/lowestprice-1 as afwijking
from tproducts p
join (
select Max(tresults.StartTime) AS maxstarttime, tresults.pID
from tresults
-- maybe adding a where clause here?
group by tresults.pID
) p_max on (p_max.pID = p.pID)
join tresults res on (res.starttime = p_max.maxstarttime and p.pID = res.pID and res.websiteID = 1)
join tsupplierproducts sp on (sp.pID = p.pID AND supplierID = 1)
join tbrands b on (b.brandID = p.BrandID)
group by p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice
Indexes are on all columns that are part of joins or where clauses.
Any help would be appreciated. Thanks!
From your SQL I assume that you are listing product based on 1 supplier (supplierID = 1) only.
Best practice is do your known filter at begin of sql to eliminate record, then use inner join to join other without filter table.
select p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice, min(price), min(price)/lowestprice-1 as afwijking
from
(select p.pID, p.BrandID p.EAN, Max(t.StartTime) AS maxstarttime
FROM tproducts p INNER JOIN tresults t on supplierID=1 and p.pID=t.pID
group by tresults.pID
) p
inner join tresults res on (res.websiteID = 1 and p.pID = res.pID and res.starttime = p_max.maxstarttime)
inner join tsupplierproducts sp on (sp.pID = p.pID)
inner join tbrands b on (b.brandID = p.BrandID)
group by p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice
from above code, I eliminate all supplierID != 1 from tproducts before join tresults.
let me know if the above sql help, and what is the EXPLAIN function result
:-)