sort particular rows using mysql order case - mysql

I have a table with incremented id from 1,2,3...and so on. What i want is just to sort the data in descending order on the basis of field 'id' except first two rows. I tried using below query:-
SELECT * FROM categories ORDER BY CASE WHEN id<3 THEN 0 ELSE id END DESC
It give me the result like
id name
5 Meal
4 Apparel
3 Electronics
1 Sports
2 Lifestyle
But output should come like
id name
1 Sports
2 Lifestyle
5 Meal
4 Apparel
3 Electronics
Is there any way to achieve this by using such query?

Try this:
SELECT *
FROM categories
ORDER BY CASE WHEN id < 3 THEN 10000 - id ELSE id END DESC;
-- ----------------------------^
-- use a very large number
Edit:
A better solution which does not require hard coding 10000:
SELECT *
FROM categories
ORDER BY CASE WHEN id < 3 THEN id ELSE 3 END, id DESC
-- ---------------------^ ^
-- ------------------------------------|
-- these numbers must be same

Change it to:
CASE WHEN id<3 THEN id ELSE ~id END
And instead of case, use IF:
IF(id<3, id, ~id)

That's because you're ordering by descending ids, so the order is 5-4-3-0-0. You can try:
SELECT * FROM categories ORDER BY CASE WHEN id<3 THEN 9999 ELSE id END DESC
But that is not a perfect solution

Related

match multiple numbers in sql and get count of all matches in rows

I have 3 rows in sql:
sno ids
1. 5,6,7
2. 6,8
3. 5,7,8
I would like to know how many users have max match of (5,6,7) in them for eg: ,Sno. 2 has 1 and Sno 3 has 2 and so on.Is there a query/way to do that or its not possible?
While I'd highly recommend normalizing your database (i.e. not storing comma delimited strings in a colum), here's one option using case and find_in_set:
select sno,
case when find_in_set(5, ids) then 1 else 0 end +
case when find_in_set(6, ids) then 1 else 0 end +
case when find_in_set(7, ids) then 1 else 0 end cnt
from yourtable
group by sno
SQL Fiddle Demo

MySQL multi-step GROUP BY without subquery

I'm working on improving some queries I inherited, and was curious if it was possible to do the following - given a table the_table that looks like this:
id uri
---+-------------------------
1 /foo/bar/x
1 /foo/bar/y
1 /foo/boo
2 /alpha/beta/carotine
2 /alpha/delic/ipa
3 /plastik/man/spastik
3 /plastik/man/krakpot
3 /plastik/man/helikopter
As an implicit intermediate step I'd like to group these by the 1st + 2nd tuple of uri. The results of that step would look like:
id base
---+---------------
1 /foo/bar
1 /foo/boo
2 /alpha/beta
2 /alpha/delic
3 /plastik/man
And the final result would reflect the number of unique tuple1 + tuple2 values, per unique id:
id cnt
---+-----
1 2
2 2
3 1
I can achieve these results, but not without doing a subquery (to get the results of the implicit step mentioned above), and then select/grouping out of that. Something like:
SELECT
id,
count(base) cnt
FROM (
SELECT
id,
substring_index(uri, '/', 3) AS base
FROM the_table
GROUP BY id, base
)
GROUP BY id;
My reason for wanting to avoid the subquery is that I'm working with a fairly large (20M rows) data set, and the subquery gets very expensive. Gut tells me it's not doable, but figured I'd ask SO...
There's no need for a subquery -- you can use count with distinct to achieve the same result:
SELECT
id,
count(distinct substring_index(uri, '/', 3)) AS base
FROM the_table
GROUP BY id
SQL Fiddle Demo
BTW -- this returns count of 1 for id 3 -- I assume that was a typo in your posting.

Mysql search text in one column

For Example our table;
İd--------Price---------Level
1 ------100-300 ------ 1,2
2 ---------200----------1
3 ------100-280--------1,3
We want search a price value is 110. 110 is between 100-300 and 100-280 so id 1 and id 2 must listed. Can we write this query with my-sql?.
Additional , we want search price and level value. Price 110 and level 2 searching. Can we write this query with my-sql?.
Thank You
Remember that database tables should be created with the idea that it will satisfy your query needs. It doesn't make sense to have a table with a price "100-300" which represents a String (or in mysql a VARCHAR) and you want to treat this as a number. So what to do?
1) The first thing i would do is re write my table schema having a minPrice and maxPrice fields, so this way you could have this:
İd----minPrice---maxPrice------level
1 ------100---------300 ------ 1,2
2 ------200---------200----------1
3 ------100---------280--------1,3
2) Then your query would be like:
SELECT id FROM Mytable x WHERE myValue >= x.minPrice AND myValue <= x.maxPrice
3) In case you also want to look for a level value. you would do:
SELECT id FROM Mytable x WHERE myValue >= x.minPrice AND myValue <= x.maxPrice AND myLevelValue IN (x.level)
Use two columns for the price ...
ID FROM TO LEVEL
1 100 300 1,2
2 200 200 1
3 100 280 1,3
Then SQL:
SELECT `level` FROM `table`
WHERE X >= `from` AND X <= `to`

How to fetch a query result on different column when we use UNION in mySQL?

i'm trying to display a MySQL query result in that form
Title 1 Title 2 Title3.
with this query :
SELECT title as titre1 FROM sequence WHERE ID_sequence = 1
UNION
SELECT title as titre2 from sequence WHERE ID_sequence = 2
UNION
SELECT title as titre3 FROM sequence WHERE ID_sequence = 3
but the result displayed in this form
Title 1 with the different ROWS (title1,2 and 3).
any idea to help thanks !
UNION'ing data will combine various data sets into a common column structure, with a row per each.
What you are looking for in this case is a subquery for each sequence, return as a column. This should do the trick. Please note that if your subquery returns more than one row, then you will get an error, but this should not be an issue in your query since you are filtering on a single ID (assuming that ID_sequence in the primary key of the sequence table).
SELECT
(SELECT title as titre1 FROM sequence WHERE ID_sequence = 1 ) AS titre1
, (SELECT title as titre2 from sequence WHERE ID_sequence = 2) AS titre2
, (SELECT title as titre3 FROM sequence WHERE ID_sequence = 3) AS titre3
UNION always adds rows onto a query - in a UNION of two queries the results from the second will appear underneath the results from the first. So UNION won't do what you want here.
This query:
SELECT
CASE ID_sequence WHEN 1 THEN title ELSE NULL END CASE as titre1,
CASE ID_sequence WHEN 2 THEN title ELSE NULL END CASE as titre2,
CASE ID_sequence WHEN 3 THEN title ELSE NULL END CASE as titre3
FROM sequence
WHERE ID_sequence > 0 AND ID_sequence < 3 ;
will give you three columns. However in any given row two of the columns will be be blank which may or may not be what you want.
If you want to have all three columns with values in every row then you need to specify some relationship between them (i.e. which Title1 goes with which Title2 etc), then use a self join. You haven't said what that relationship should be, so I can't give an example for that.

How to use GROUP BY to retrieve a result set with priority on alphabeticization for CASE field?

In a previous question I asked, someone suggested the MAX(value) syntax to prioritize on alphbetization
How to use GROUP BY to retrieve a result set with priority on alphabeticization
However I'm dealing with the CASE statement and using MAX(CASE statement) is syntactically incorrect.
SELECT id,
CASE
WHEN filename LIKE '%.mp3' THEN 'song'
ELSE 'other' END as type
FROM filenames
1 song
2 song
2 other
3 other
3 song
SELECT id,
CASE
WHEN filename LIKE '%.mp3' THEN 'song'
ELSE 'other' END as type
FROM filenames
GROUP BY id;
1 song
2 song
3 other
How would I prioritize the type field for those which come alphabetically last? Ex. the result set should be
1 song
2 song
3 song
I'd like to avoid nested statements if possible. Can this be done with the MAX(type) syntax?
You can use following
SELECT id,
CASE
WHEN filename LIKE '%.mp3' THEN 'song'
ELSE 'other' END as type
FROM filenames
GROUP BY id DESC;
DESC will give you descending order