Sorting special name to end in database - mysql

I want to sort a mysql-table
select id,name from tbl order by name asc;
returns
1 name1
2 name2
4 name3
5 name4
8 name5
How to order that e.g name 3 goes to end of the table like
select id,name from tbl order by ["name is name3????"],name asc;
returns
1 name1
2 name2
5 name4
8 name5
4 name3
Thank you

With case you can return a value based on a condition. So you can return 1 for name3 and 0 for other names. Primarily sort on this value to put name3 in the back. The secondary sort value is the name, so that the other names are still sorted alphabetically.
select
id, name
from
tbl
order by
case when name = 'name3' then 1 else 0 end,
name
Strawberry just taught me in the comment that you could also use the function field to accomplish this. This is especially handy and more compact, if you want to specify a specific sort for a number of names. Using case that would quickly become bulky. Field returns the index of the first string in the list of other strings, so field(name, 'name3', 'name4') would return 1 for 'name3' and 2 for 'name4' and 0 for all other names.
Your query would then look like this:
select
id, name
from
tbl
order by
field(name, 'name3'),
name

Related

SQL - how to add a value with a condition to a selection?

I have the following table structure:
name
value
success
name 1
10
0
name 2
20
0
name 2
30
1
And my query is:
SELECT name, SUM(value) as valueTotal FROM TableName GROUP BY name
The result is:
name
valueTotal
name 1
10
name 2
50
Now I want to add a new column which will contain the sum of only successful rows. But if I add this condition, it will apply to all selected fields:
SELECT name, SUM(value) as valueTotal, SUM(value) as successValueTotal FROM TableName WHERE success = 1 GROUP BY name
Here is the result I want to get:
name
valueTotal
successValueTotal
name 1
10
0
name 2
50
30
How can I add a field with a separate condition that does not affect the main query? Thx)
You can use the SUM function with a conditional aggregation on whether success is 1 or not. When success is 1, then take the value of the value field, otherwise sum up 0.
SELECT name,
SUM(value) AS valueTotal,
SUM(IF(success = 1, value, 0)) AS successValueTotal
FROM TableName
GROUP BY name
Try it here.
This is the typical use case for CASE WHEN:
SELECT name,
SUM(value) AS valueTotal,
SUM(CASE WHEN success = 1 THEN value ELSE 0 END) AS successValueTotal
FROM TableName
GROUP BY name
You can (like lemon showed) also use an if clause in MYSQL. This is a bit shorter, but the query will not work on every DB while CASE WHEN does. So I think both is fine.

Is it posible to use multiple values from a json list in a mysql where clause?

I have this table filled with values, and it's all structured in JSON.
PersonID
ValueID
Value
1
1
{"Values":[{"ID":1,"Value":true},{"ID":2,"Value":true}]}
1
2
{"Values":[{"ID":2,"Value":false},{"ID":3,"Value":true}]}
So I was wondering if there was any way to query on the ID and value at the same time, so I etc. would be able to search for "ID":1 and "Value":true and then it would return the first row.
I've tried to use JSON_CONTAINS_PATH, JSON_CONTAINS, JSON_SEARCH but none of them takes into account that I want to search in a list, I have tried with the $.Values[0].ID and that returns the id but I need to loop all of them through in the where, else I would only search the first index of the JSON array.
Can anyone point me in the right direction?
SELECT
PersonID,
ValueID,
x1.*
FROM table1
cross join JSON_TABLE(table1.Value,
'$.Values[*]' COLUMNS( ID INTEGER PATH '$.ID',
Value INTEGER PATH '$.Value'
)) as x1
output:
PersonID
ValueID
ID
Value
1
1
1
1
1
1
2
1
1
2
2
0
1
2
3
1
see: DBFIDDLE
SELECT *
FROM table1
WHERE table1.value->'$.Values[0]' = JSON_OBJECT('ID',1,'Value',true)

MySQL - ORDER BY multiple words, then alphabetically?

How can I change this part of the query to have multiple words ordered first in sequence, then the rest of the results alphabetically?
ORDER BY CASE WHEN name LIKE '%Professional%' THEN 0 ELSE 1 END asc, name asc
So, it needs to be:
'%Professional%' 1
'%Leader%' 2
'%Advocate%' 3
'%Clinician%' 4
'%Educator%' 5
'%Scholar%' 6
Then all other results alphabetically.
You can just expand your CASE expression with each of the desired words:
ORDER BY
CASE WHEN name LIKE '%Professional%' THEN 1
WHEN name LIKE '%Leader%' THEN 2
WHEN name LIKE '%Advocate%' THEN 3
WHEN name LIKE '%Clinician%' THEN 4
WHEN name LIKE '%Educator%' THEN 5
WHEN name LIKE '%Scholar%' THEN 6
ELSE 7
END,
name

SQL: How to replace an entire field if it matches a string?

I am trying to replace an entire field from a database when it matches a certain string.
For example:
TABLE_FRUITS contains
ID NAME
---------------
1 APPLE
2 ORANGE
3 PASSIONFRUIT
4 BANANA
5 DRAGONFRUIT
6 KIWI
7 STRAWBERRY FRUIT
Now If I try to select column NAME, and if a field contains the string 'FRUIT', it should replace that whole field to another string, like 'SAMPLE'.
Expected result:
select NAME from TABLE_FRUITS;
would return:
APPLE
ORANGE
SAMPLE
BANANA
SAMPLE
KIWI
SAMPLE
I am not sure if I should use replace or substr/instr.
If you're using MySQL, you could use something like
SELECT IF(NAME LIKE '%FRUIT%', 'SAMPLE', NAME) AS NAME FROM TABLE_FRUIT
In other varieties of SQL you will probably need to use a CASE expression:
SELECT CASE WHEN NAME LIKE '%FRUIT%' THEN 'SAMPLE' ELSE NAME END AS NAME FROM TABLE_FRUIT
Use case when:
select case when name like '%fruit%' then 'Sample' else name end from tablename
You can use CASE
select case when name like '%FRUIT%' then 'sample' else name end
from table_fruit

how can extract part of a text from a field in mysql?

I have fields like this:
-----------------
id | name
-----------------
1 | name123
-----------------
2 | name
-----------------
3 | name456
-----------------
4 | name
I want to extract rows which have digit in name and a field that contains the number like this
------------------------------
id | name | number
-----------------------------
1 | name123 | 123
-----------------------------
3 | name456 | 456
how can we find the records that have digit and extract digit as a new field?
Here is another way to do with mysql
SELECT
id,
name,
SUBSTRING(
name,LEAST (
if (Locate('0',name) >0,Locate('0',name),999),
if (Locate('1',name) >0,Locate('1',name),999),
if (Locate('2',name) >0,Locate('2',name),999),
if (Locate('3',name) >0,Locate('3',name),999),
if (Locate('4',name) >0,Locate('4',name),999),
if (Locate('5',name) >0,Locate('5',name),999),
if (Locate('6',name) >0,Locate('6',name),999),
if (Locate('7',name) >0,Locate('7',name),999),
if (Locate('8',name) >0,Locate('8',name),999),
if (Locate('9',name) >0,Locate('9',name),999)
),LENGTH(name)
) as number
from users
having number <> '' ;
you can use MySQL's string conversion on an int to strip out the name like so
SELECT
t.id,
t.name,
REVERSE(REVERSE(t.name)+ 0) AS num,
REPLACE(t.name,REVERSE(REVERSE(t.name)+ 0),'') AS actualname
FROM foobar t
HAVING num <> 0
the trick with this is by adding a 0 mysql is comparing the numeric value in the name... however the name has to start with a number... so I reverse it do the calculation and then reverse again... NOTE all of your names have to start with the name and end with a number for this to work for all of them
FIDDLE DEMO
EDIT:
since you say that some can start with a number and others end with a number.. then try this
SELECT
t.id,
t.name,
REVERSE(REVERSE(t.name)+ 0) AS num,
REPLACE(t.name,REVERSE(REVERSE(t.name)+ 0),'') AS actualname
FROM foobar t
HAVING num <> 0
UNION ALL
SELECT
t.id,
t.name,
t.name + 0 AS num,
REPLACE(t.name,t.name + 0,'') AS actualname
FROM foobar t
HAVING num <> 0
ANOTHER DEMO
Another way, assuming the number you want is at the end of the string. REVERSE() to put the number part in front, then CONVERT() to make it a number and strip off the text, then REVERSE() again WHERE name ends in a number. Feels like a kludge though:
select id, name, reverse(convert(reverse(name),signed ))
from tbl
where name REGEXP '[0-9]+$';
SQL Fiddle Example