MySQL aliased subquery cannot be used in where clause - mysql

I have a query given below that returns all the data asked. Then in the next query I need to write I need to restrict the output to where the subquery is greater than 5.
I will show examples but I cannot understand why I cannot do what I am attempting.
Query without restriction
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Screenshot of output
Attempt at query with restrictions
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
where Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Error

You can't use a derived column in a where clause, need to use HAVING:
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
HAVING Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;

Related

Want to reduce the My SQL 5.7 run time on my query

Basically I want to find the next date when next message is execute for the customer. I run the query and get the desired output. However, MY SQL is taking more than 4 minutes for a large dataset.
SELECT
t1.cid, t1.requesttime,
(SELECT t2.um_requesttime
FROM db.table t2
WHERE
t2.um_CID = t1.um_CID AND
t2.um_requesttime > t1.um_requesttime
ORDER BY t2.um_requesttime
LIMIT 1
) AS lead_date
FROM db.table t1 order by
um_CID,um_requesttime
I tried this query but it gives me error on it.
SELECT
t1.cid, t1.requesttime,
(SELECT t2.um_requesttime
FROM db.table t2
WHERE
t2.um_CID = t1.um_CID AND
t2.um_requesttime > t1.um_requesttime
ORDER BY t2.um_requesttime LIMIT 1
) AS lead_date
FROM db.table t1
USE INDEX for ORDER BY (t1.um_CID,t1.um_requesttime)
So if you could help me how we can optimize the time and make it more faster then it would be great.
Could you try whether the following query using JOIN is a possible workaround?
SELECT
t1.cid,
t1.requesttime,
MIN(t2.um_requesttime) AS lead_date
FROM
db.table t1 LEFT OUTER JOIN db.table t2
ON t2.um_CID = t1.um_CID AND t2.um_requesttime > t1.um_requesttime
GROUP BY
t1.cid,
t1.requesttime;
I mean the right indexes should to increase the query performance:
ALTER TABLE `table`
ADD INDEX `um_CID_ix` (`um_CID`),
ADD INDEX `um_requesttime_ix` (`um_requesttime`);
Here the fiddle SQLize.online

How can I optimize the following SQL query

Right now it is taking a long long time to run.
The query is:
select count(id), variety_id, name
from tblItem
where order_id IN (
select order_id
from tblItem
where variety_id=4005
order by order_id DESC)
AND variety_id != 4005
GROUP BY variety_id
order by count(id) DESC
LIMIT 5;
I have indexes on variety_id and order_id. I'm basically trying to build a recommendation engine. The query is looking for the top 5 items people buy when they also bought variety_id 4005. But like i said it takes way to long to run.
Does anyone have a way to optimize this query?
Try this:
select count(t1.id), t1.variety_id, t1.name
from tblItem t1
inner join tblItem t2 ON t2.order_id = t1.order_id and t2.variety_id = 4005
where t1.variety_id != 4005
GROUP BY t1.variety_id, t1.name
ORDER BY count(t1.id) DESC
LIMIT 5;
I've often found that MySQL optimizes WHERE ... IN (SELECT ...) poorly, and JOIN works better; I've read that recent MySQL versions are better, so it may be version-dependent. Also, you should use COUNT(*) unless the column can be NULL and you need to ignore the null values in the count.
SELECT COUNT(*) count, variety_id, name
FROM tblItem AS t1
JOIN (SELECT DISTINCT order_id
FROM tblItem
WHERE variety_id = 4005) AS t2
ON t1.order_id = t2.order_id
WHERE t1.variety_id != 4005
GROUP BY variety_id
ORDER BY count DESC
LIMIT 5
The subquery with DISTINCT is needed to prevent multiplying the counts by the number of matching rows in the cross-product.

"Cannot used in global ORDER clause" with mysql ordering

I have problem with this SQL query:
(SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage) ORDER BY tb1.id DESC
for some reason I'm getting:
Table 'tb1' from one of the SELECTs cannot be used in global ORDER clause
any advice?
Thanks
The reason it doesn't work is the outer ORDER BY can't "see" tb1 - it sees the results of the inner subquery. So in a syntactically correct version of your query, you would simply ORDER BY id :
(SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage) ORDER BY id DESC
But, as others are pointing out, this can more simply written as a single query ordered by id
If you put parentheses around your select then the inner table will not be visible outside
SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage, tb1.id DESC
And you can specify multiple columns in one order by clause
When you close your parentheses after select statement, your second order by clause becomes invalid. Instead try merging your order by columns in a single order by statement like the following:
SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage, tb1.id DESC

sql pulling from sub query

Is it possible to pull 2 results from a sub query in a sql statement?
I have:
"SELECT
(SELECT bid FROM auction_bids WHERE itemID=a.id ORDER BY bid DESC LIMIT 1) as topbid,
a.* FROM auction_items a ORDER BY a.date DESC LIMIT 15"
The part where it returns the topbid, i'd also like it to pull not only bid (as topbid) but also date (as topdate) as well. How can I do that? Do I need another sub query or can it pull both in one?
Dependent subquery (depending on some values outside, like a.id in your case) is not a very efficient way to find maximum values in subsets.
Instead use a subquery with GROUP BY:
SELECT b.topbid, b.topdate, a.*
FROM auction_items a
LEFT JOIN
( SELECT itemID, MAX(bid) as topbid, MAX(date) as topdate
FROM auction_bids
GROUP BY itemID ) b
ON a.id = b.itemID
ORDER BY a.date DESC
LIMIT 15

Join statement...how do do ORDER BY?

I have the following LEFT JOIN statement (though probably also applies to even a simpler SELECT statement):
SELECT * FROM t1 LEFT JOIN t2 ON t2.c = t1.c WHERE t1.m LIKE 'captain%' GROUP BY
t1.c ORDER BY t2.date DESC LIMIT 0,10
The results get returned but they are not ordered by t2.date DESC...I imagine this is due to having the GROUP BY statement in there. How can I group the results AND order them?
thx
Put your query in a subquery and then use ORDER BY.
SELECT *
FROM
(SELECT *
FROM t1 LEFT JOIN t2 ON t2.c = t1.c
WHERE t1.m LIKE 'captain%'
GROUP BY t1.c DESC LIMIT 0,10) l1
ORDER BY date
In normal SQL it would not even be allowed to ORDER BY t2.date because you aren't grouping on it and you are not using an aggregate function on it, so you can't select it.
Anyway, as MySQL just picks values from the rows in an undefined manner and afterwards sorts them, the t2.date column in your results should be sorted. Please show some actual output.