Alternate to ORDER BY subquery - mysql

From the database at http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_orderby2, for example (Click "Run SQL"), I want to list the customer who has the largest CustomerID that is greater than 80 first among a list of all customers from USA. So I use
SELECT * FROM Customers
WHERE Country = 'USA'
ORDER BY CustomerID = (SELECT MAX(CustomerID) FROM Customers
WHERE CustomerID > 80 AND Country = 'USA') DESC, PostalCode;
but this is not the real query I'm using. If the SELECT... FROM... WHERE... portion of the query is more complex, what is a more elegant query?
The actual query I am trying to modify is
SELECT post.postid, post.visible, post.userid, post.parentid, post.vote_count
FROM " . TABLE_PREFIX . "post AS post
WHERE post.threadid = $threadid
AND post.visible IN (1" . (!empty($deljoin) ? ", 2" : "") .
($show['approvepost'] ? ", 0" : "") . ")
ORDER BY post.postid = {$threadinfo['firstpostid']} DESC, post.vote_count > 5 DESC,
post.dateline $postorder
where the post.vote_count > 5 DESC portion I am trying to replace with only the largest post.vote_count that is larger than 5. So I use:
SELECT post.postid, post.visible, post.userid, post.parentid, post.vote_count
FROM " . TABLE_PREFIX . "post AS post
WHERE post.threadid = $threadid
AND post.visible IN (1" . (!empty($deljoin) ? ", 2" : "") .
($show['approvepost'] ? ", 0" : "") . ")
ORDER BY post.postid = {$threadinfo['firstpostid']} DESC, post.vote_count = (
SELECT MAX(post.vote_count)
FROM " . TABLE_PREFIX . "post AS post
WHERE post.threadid = $threadid
AND post.visible IN (1" . (!empty($deljoin) ? ", 2" : "") .
($show['approvepost'] ? ", 0" : "") . ")
AND post.vote_count > 5
)
DESC, post.dateline $postorder
and all is good. But you can imagine a more complex query, perhaps with INNER JOIN, whose SELECT... FROM... WHERE... etc. must all be duplicated in the subquery.
So my question is, I suspect, can you order query results so the first item (within those results) has the maximum of a field, and the remainder ordered otherwise, without essentially rewriting the entire query in a subquery?

MySQL does not support CTE's, which would have been the perfect solution to simplify your query. They can be emulated with a view though :
CREATE VIEW c AS (SELECT Customer.* FROM Customer WHERE Country = "USA");
SELECT c.* FROM c ORDER BY CustomerID = (SELECT MAX(CustomerID) FROM c) DESC;
DROP VIEW c;
In your case, this would give :
CREATE VIEW p AS (
SELECT post.postid, post.visible, post.userid, post.parentid, post.vote_count
FROM " . TABLE_PREFIX . "post AS post
WHERE post.threadid = $threadid
AND post.visible IN (1" . (!empty($deljoin) ? ", 2" : "") .
($show['approvepost'] ? ", 0" : "") . ")
);
SELECT p.* FROM p
ORDER BY p.postid = {$threadinfo['firstpostid']} DESC, p.vote_count = (
SELECT MAX(p.vote_count)
FROM p
WHERE p.vote_count > 5
)
DESC, post.dateline $postorder;
DROP VIEW p;

This query will list data in descending order of CustomerID
SELECT * FROM Customers
WHERE Country = 'USA'
ORDER BY CustomerID DESC, PostalCode;

Related

How to convert sql to hql with join and max

I am trying to make this query in hql so i don't have to mapper the query result into my java object , but after trying different options, i still can't make it work. Is it possible to perform this query in hql in any way? The query is:
select t.*
from part_movement t
join
( select id_block_movement, max(start_date) as somedate
from part_movement
where id_area_final_destination = 1
and ((id_area_destination != id_area_final_destination and id_user_receiver is not null) or
(id_area_destination = id_area_final_destination and id_user_receiver is null))
group by id_block_movement
) s
on s.id_block_movement = t.id_block_movement
and s.somedate= t.start_date;
ok i got it finally!! It was: (feels wired answearing myself without having any answear from someone else )
Query q2 = s.createQuery(" from PartMovement t "
+ " WHERE t.areaByIdAreaFinalDestination = ? "
+ " AND t.startDate IN (select max(b.startDate) from PartMovement b "
+ " WHERE ((b.areaByIdAreaDestination != b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is not null) OR "
+ " (b.areaByIdAreaDestination = b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is null)) "
+ " group by b.idBlockMovement )");

How to subtract two calculated fields from the same table in MySQL?

SELECT *,
SUM(price+shipping+paypalfee+storefee) AS totalcost,
customerpaid AS totalrevenue,
(totalcost - totalrevenue) AS profit
FROM tblsales
GROUP BY orderno
HAVING " . $having . "
ORDER BY $sort $order
LIMIT $offset,$rows
If I omit (totalcost - totalrevenue) as profit the query works fine. How could I calculate PROFIT in the same query using totalcost and totalrevenue?
The answer to your question is that you have to repeat the expressions:
select *, sum(price+shipping+paypalfee+storefee) as totalcost
customerpaid as totalrevenue,
(sum(price+shipping+paypalfee+storefee) - customerpaid) as profit
from tblsales
group by orderno
having " . $having . "
order by $sort $order
limit $offset, $rows;
You are not allowed to use a column alias in the same select where it is defined.
And, your query looks weird. Any query that has select * and group by is suspect. You have many columns (presumably) whose value will come from an indeterminate row for each group. You should explicitly list the columns in general, but you should especially do so for a group by.
You can do like this
SELECT * , (totalcost - totalrevenue) AS profit FROM(
SELECT *,
SUM(price+shipping+paypalfee+storefee) AS totalcost,
customerpaid AS totalrevenue,
FROM tblsales
GROUP BY orderno
HAVING " . $having . "
ORDER BY $sort $order )
LIMIT $offset,$rows

LIMIT CLAUSE With union

I have this kind of query. I am using limit, but this query gives me 20 results. Can anybody tell me why
SELECT
*,
`tablename`.`bookmark_id` as `bookmark_id`,
`tablename`.`bookmark_date` as `bookmark_date`
FROM ( (" + sql1 + ")
UNION ALL (" + sql2 + ")
UNION ALL (" + sql3 + ") ) AS tablename
WHERE `bookmark_id`
NOT IN
(SELECT `table1`.`bookmark_id`
FROM (
(SELECT `user_bookmarks`.`bookmark_id`
FROM `user_bookmarks`
WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id`
AND `user_id` = 26)
UNION
(SELECT `bookmark_id`
FROM `user_deleted_bookmarks`
WHERE `user_id` = ?)
) AS `table1`)
GROUP BY bookmark_id
ORDER BY `bookmark_date`
DESC limit 17, 20
Thanks
From the SELECT docs
With one argument, the value specifies the number of rows to return from the beginning of the result set:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
I think you want LIMIT 16, 4
When you use limit, second argument is number of results to return.
See : http://dev.mysql.com/doc/refman/5.0/en/select.html
In your case you want :
SELECT .... LIMIT 16,4
You will get 4 rows : 17, 18, 19 and 20.
SELECT *,`tablename`.`bookmark_id` as `bookmark_id`,`tablename`.`bookmark_date` as `bookmark_date` FROM ( (" + sql1 + ") union all (" + sql2 + ") union all (" + sql3 + ") ) AS tablename WHERE `bookmark_id` NOT IN (SELECT `table1`.`bookmark_id` FROM ((SELECT `user_bookmarks`.`bookmark_id` FROM `user_bookmarks` WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id` AND `user_id` = 26) UNION (SELECT `bookmark_id` FROM `user_deleted_bookmarks` WHERE `user_id` = ?)) AS `table1`) GROUP BY bookmark_id ORDER BY `bookmark_date`
DESC limit 16, 4;
for getting result 17,18,19,20
it's count start from 17th position and give next 4 values

MySQL procedure - how to improve performance of query?

I have MySQL procedure which is collecting data from 3 tables:
dossier
courrier
courrier_concerne_dossier
Simply I just can't use select * from... I need every dossier_str separated (one dossier_str in each column and all in one big result set).
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 1) as 'dossier1_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier1_oid) as 'dossier1_str',
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 1,1) as 'dossier2_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier2_oid) as 'dossier2_str',
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 2,1) as 'dossier3_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier3_oid) as 'dossier3_str',

Order of "id" changed in subquery?

I have this query
SELECT bul.id
FROM bul
WHERE id IN (SELECT hotid AS parentid
FROM likehot
WHERE hotid IN (SELECT id
FROM bul
WHERE DATE >= '1315976410')
GROUP BY hotpid
ORDER BY COUNT( hotid ) DESC )
when I runt this inner query
SELECT id
FROM bul
WHERE DATE >= '1315976410')
GROUP BY hotpid
ORDER BY COUNT( hotid ) DESC
I get
parentid
3655
3656
3622
3644
and when I run whole query I get
parentid
3656
3655
3622
3644
I really don't understand why the order of the ids change?
SOLUTION :-
<?php
$query_hotpress_like = "SELECT hotid AS parentid FROM likehot WHERE hotid IN (SELECT id FROM bul WHERE DATE >= '" . (time() - (24 * 60 * 60)) . "') GROUP BY hotid ORDER BY COUNT( hotid ) DESC";
$exe_hotpress_like = execute_query($query_hotpress_like, true, "select");
$temp_like1 = array();
foreach ($exe_hotpress_like as $kk => $exe_like) {
$temp_like1[] = "'" . $exe_like['parentid'] . "'";
}
$temp_like = str_replace(",''", "", implode(',', $temp_like1));
$query_hotpress = "SELECT bul.id,photo_album_id,eventcmmnt_id,link_url,youtubeLink,link_image,id, mem_id, subj, body, bul.date,parentid, from_id, visible_to,image_link,post_via FROM bul WHERE id IN ($temp_like) ORDER BY FIELD(id,$temp_like ) LIMIT 5";
?>
execute_query() is the inbuilt function to get the result of query.
That happens because for IN operator order doesn't matter.
If you need to sort outer query - sort outer query.
Since you didn't specify an order for the "whole" query, the database is at liberty to return rows in any order it wants. The specific order you get is a result of how looking up rows is done when using the IN operator.
On your other query you are specifying an order yourself, so the database has to honor it.