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.
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)
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
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
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