We have a DB called transaction. It has user_id, date, value and so on. I use pagination in my query also. I have thousands of record in my table which has user_id equal to 2 or other value. put the user_id = 2 at the very last page.
I want to sort the result like this:
sort the results by date but if the user_id= 2 , put all results associated with the user_id= 2 at the end.
to be more clear, I show you what I want in the below.
-------------------------------------
| ID | user_id | date | ......
-------------------------------------
| 1 | 10 | 2018-10-20 |
-------------------------------------
| 2 | 11 | 2018-10-21 |
-------------------------------------
| 3 | 2 | 2018-10-22 |
-------------------------------------
| 4 | 2 | 2018-10-23 |
the results have to be like this:
first: ID = 2, second: ID = 1, third: ID = 4, last: ID = 3
tip *:
I use field function but unfortunately in vain.
ORDER BY FIELD(user_id, 2) DESC, date DESC
You may try using a CASE expression in your ORDER BY clause:
SELECT *
FROM yourTable
ORDER BY
CASE WHEN user_id = 2 THEN 1 ELSE 0 END,
date DESC;
I'm not sure if you want each group sorted by date ascending or descending. If you want ascending date order, then remove the DESC keyword at the end of my query.
Related
I have a table with a column to maintain the state of the record. i.e.
-----------------------------
| id | desc | state |
-----------------------------
| 1 | desc 1 | Complete |
| 2 | desc 2 | Open |
| ... | ... | ... |
-----------------------------
I want fetch the records in the order of 'Open' followed by 'Complete'. Can I get this done using one SQL query? If so, how should I write it?
Yes, you could do this with the ORDER BY statement and FIELD function:
SELECT * FROM table1 ORDER BY FIELD(state, 'Open', 'Complete')
Try something like this:
select *
from table_name
order by decode (state, 'Open', 1, 'Complete', 2, 3)
I have table named posts with 3 columns which are id, details, date which contains the following data in ascending order:
+----+----------+-------+
| id | details | date |
+----+----------+-------+
| 1 | details1 | date1 |
| 2 | details2 | date2 |
| 3 | details3 | date3 |
| 4 | details4 | date4 |
+----+----------+-------+
I want to select data in descending order but I want to leave the first row details, like I want to leave row 4th id details, details4, date4, but then I want to select data from id 3 to 2 in, like order by id desc limit 2 but leave the first row from last
You can use the query with ORDER BY DESC LIMIT 1, n
That way, n is the amount of rows you want to fetch, and you're skipping the first row of the result by using LIMIT 1, .
WITH a AS (
SELECT 1 i
UNION ALL
SELECT 2 i
UNION ALL
SELECT 3 i
UNION ALL
SELECT 4 i
)
, b as (
SELECT TOP 1 i FROM a ORDER BY i DESC
)
SELECT *
FROM A
EXCEPT
SELECT * FROM B
ORDER BY i DESC
I need to create a number adding all the values i can find in the db related to a specific customer.
Ex.
| Cust. | Value |
| 1 | 3 |
| 2 | 1 |
| 1 | 1 |
| 2 | 1 |
| 3 | 5 |
The result i want is : Customer #1 = 4, Customer #2 = 2; Customer #3 = 5.
There is a way to do that right into the mysql query?
Try Below query.
Select CONCAT('Customer #' , cust) as customer , sum(Value)
FROM customer_table
Group By cust
You want to SUM the values with a specific GROUP BY clause. Think of the GROUP BY as dividing rows into buckets and the SUM as aggregating the contents of those buckets into something useful.
Something like:
SELECT SUM(Value) FROM table GROUP BY Cust
I want to show first two top voted Posts then others sorted by id
This is table
+----+-------+--------------+--------+
| Id | Name | Post | Votes |
+====+=======+==============+========+
| 1 | John | John's msg | -6 |
| 2 |Joseph |Joseph's msg | 8 |
| 3 | Ivan | Ivan's msg | 3 |
| 4 |Natalie|Natalie's msg | 10 |
+----+-------+--------------+--------+
After query result should be:
+----+-------+--------------+--------+
| Id | Name | Post | Votes |
+====+=======+==============+========+
| 4 |Natalie|Natalie's msg | 10 |
| 2 |Joseph |Joseph's msg | 8 |
-----------------------------------------------
| 1 | John | John's msg | -6 |
| 3 | Ivan | Ivan's msg | 3 |
+----+-------+--------------+--------+
I have 1 solution but i feel like there is better and faster way to do it.
I run 2 queries, one to get top 2, then second to get others:
SELECT * FROM table order by Votes desc LIMIT 2
SELECT * FROM table order by Id desc
And then in PHP i make sure that i show 1st query as it is, and on displaying 2nd query i remove entry's that are in 1st query so they don't double.
Can this be done in single query to select first two top voted, then others?
You would have to use subqueries or union - meaning you have a single outer query, which contains multiple queries inside. I would simply retrieve the IDs from the first query and add a id not in (...) criterion to the where clause of the 2nd query - thus filtering out the posts retrieved in the first query:
SELECT * FROM table WHERE Id NOT IN (...) ORDER BY Id DESC
With union the query would look like as follows:
(SELECT table.*, 1 as o FROM table order by Votes desc LIMIT 2)
UNION
(SELECT table.*, 0 FROM table
WHERE Id NOT IN (SELECT Id FROM table order by Votes desc LIMIT 2))
ORDER BY o DESC, if(o=1,Votes,Id) DESC
As you can see, it wraps 3 queries into one and has a more complicated ordering as well because in union the order of the records retrieved is not guaranteed.
Two simple queries seem to be a lot more efficient to me in this particular case.
There could be different ways to write a query that returns the rows in the order you want. My solution is this:
select
table.*
from
table left join (select id from table order by votes desc limit 2) l
on table.id = l.id
order by
case when l.id is not null then votes end desc,
tp.id
the subquery will return the first two id ordered by votes desc, the join will succeed whenever the row is one of the first two otherwise l.id will be null instead.
The order by will order by number of votes desc whenever the row is the first or the second (=l.id is not null), when l.id is null it will put the rows at the bottom and order by id instead.
I have a table, and would like to sort by following rule.
I do the SQL as:
(1) select * from table orderby rank;
(2) select * from table orderby LENGTH(str);
but how can I combine those two SQLs base on (if rank>0) statment?
the idea would be like
subTable_1 which rank>0, than sort by rank;
subTable_2 which rank==0, than sort by str.length;
result=subTable_1 + subTable_2;
Many thanks
table:
| str |rank|
| ab | 2 |
| abcd | 5 |
| abc | 0 |
| a | 0 |
result:
| str |rank|
| abcd | 5 |
| ab | 2 |
| a | 0 |
| abc | 0 |
Pretty simple. Just try the following:
SELECT * FROM table
ORDER BY rank DESC, LENGTH(str) ASC;
Since rank of 0 will always be last in the list when sorted DESC, you can use the simple order by that sawrar026 shows:
SELECT * FROM table
ORDER BY rank DESC, LENGTH(str)
If you had a different condition, or if rank could be negative and you only wanted to sort where it was zero, you'd want two case statements, so you can control the order, changing the criteria in the case statements to suit:
SELECT *
FROM Table1
ORDER BY CASE WHEN rank>0 THEN rank ELSE 0 END DESC
,CASE WHEN rank=0 THEN LENGTH(str) ELSE 0 END