MySQL converting enum values to integer values - mysql

I have a table which includes an ENUM field with values 'B', 'N', 'F', and 'V'. I would like to assign each of these letters a weight:
B: -2
N: -1
F: 1
V: 2
These weights should appear in a column in a select statement. Finally, I want to add these values together. Is this possible?
The goal is to do this in django, but using MySQL will also work.

Use a CASE expression:
select sum(case enum_field
when 'B' then -2
when 'N' then -1
when 'F' then 1
when 'V' then 2
end) as total_sum
from your_table

select sum(case when enum_field = 'B' then -2
when enum_field = 'N' then -1
when enum_field = 'F' then 1
when enum_field = 'V' then 2
end) as total_sum
from your_table

Related

MYSQL show case value even if the case does not exist in dababase

http://sqlfiddle.com/#!9/027e1e/19
sample dataset here:
CREATE TABLE IF NOT EXISTS `test` (
`mode` varchar(10),
`value` int(3)
);
INSERT INTO `test` (`mode`, `value`) VALUES
('xx-a', '1'),
('xx-a', '1'),
('xx-c', '2'),
('xx-d', '3');
SQL query here:
SELECT CASE
WHEN mode LIKE '%-a' THEN 'a'
WHEN mode LIKE '%-b' THEN 'b'
ELSE 'c'
END AS channel,
IFNULL(SUM(value), 0)
FROM test
GROUP BY channel
When the value '%-b' does not exist in the database, it returns only 2 rows with 'a' and 'c'.
I need it to return 3 rows for all a, b, and c where b shows 0.
Thanks
A solution would be to use union all:
select
'a' channel,
sum(case when mode like '%-a' then value else 0 end) sum_value
from mytable
union all select
'b',
sum(case when mode like '%-b' then value else 0 end)
from mytable
union all select
'c',
sum(case when mode not like '%-a' and mode not like '%-b' then value else 0)
from mytable
Try this please
SELECT
CASE
WHEN mode LIKE '%-a' THEN 'a'
WHEN mode LIKE '%-b' THEN 'b'
ELSE 'c'
END AS channel,
IFNULL(SUM(value), 0),
IFNULL(COUNT(value), 0)
FROM database GROUP BY channel
UNION
SELECT 'b',0,0 FROM dual
WHERE not exists
(SELECT 1 FROM database WHERE mode LIKE '%-b')

MYSQL Calculate average of a specific occurance in a column

I need to calculate the average of occurrences in a dataset for a given value in a column. I made an easy example but in my current database contains around 2 inner joins to reduce it to 100k records. I need to perform the following select distinct statement for 10 columns.
My current design forces an inner join for each column. Another constraint is that I need to perform it at least 50-100 rows for each name in this example.
I need to figure out an efficient way to calculate this values without using too many resources while making the query fast.
http://sqlfiddle.com/#!9/c2378/3
My expected Result is:
Name | R Avg dir | L Avg dir 1 | L Avg dir 2 | L Avg dir 3
A 0 .5 .25 .25
Create table query:
CREATE TABLE demo
(`id` int, `name` varchar(10),`hand` varchar(1), `dir` int)
;
INSERT INTO demo
(`id`, `name`, `hand`, `dir`)
VALUES
(1, 'A', 'L', 1),
(2, 'A', 'L', 1),
(3, 'A', 'L', 2),
(4, 'A', 'L', 3),
(5, 'A', 'R', 3),
(6, 'A', 'R', 3)
;
Example Query:
SELECT distinct name,
COALESCE(( (Select count(id) as 'cd' from demo where hand = 'L' AND dir = 1) /(Select count(id) as 'fd' from demo where hand = 'L')),0) as 'L AVG dir'
FROM
demo
where hand = 'L' AND dir = 1 AND name = 'A'
One option is to use conditional aggregation:
SELECT name,
count(case when hand = 'L' and dir = 1 then 1 end) /
count(case when hand = 'L' then 1 end) L1Avg,
count(case when hand = 'L' and dir = 2 then 1 end) /
count(case when hand = 'L' then 1 end) L2Avg,
count(case when hand = 'L' and dir = 3 then 1 end) /
count(case when hand = 'L' then 1 end) L3Avg,
count(case when hand = 'R' and dir = 3 then 1 end) /
count(case when hand = 'R' then 1 end) RAvg
FROM demo
WHERE name = 'A'
GROUP BY name
Updated Fiddle Demo
Please note, I wasn't 100% sure why you wanted your RAvg to be 0 -- I assumed you meant 100%. If not, you can adjust the above accordingly.

how to perform a count on a column where a value is X

is there a way of performing a count operation with SQL where the column equals X
and ideally a separate count for when the same column equals Y and again for Z?
SELECT yourcolumn, COUNT(*) AS cnt
FROM yourtable
WHERE yourcolumn IN ('X', 'Y', 'Z')
GROUP BY yourcolumn
Something like this ?
select
sum(case when val = 'x' then 1 else 0 end) as countX
,sum(case when val = 'y' then 1 else 0 end) as countY
,sum(case when val = 'z' then 1 else 0 end) as countZ
from table
I believe the following (shorter) statement should work for MySQL:
SELECT COUNT(val='X'), COUNT(val='Y'), COUNT(val='Z') FROM ...
I would suggest the following:
SELECT YourColumn, COUNT(<Any Column of your table>)
FROM YourTable
GROUP BY YourColumn

Select more than 1 columns on condition

Tell please how can select 2 or more columns on condition? I trying this, but not works
SELECT
CASE
WHEN 1=1 THEN 'A', 'B'
ELSE 'C', 'D'
END
If trying select only 1 value
WHEN 1=1 THEN 'A'
ELSE 'C'
it works
Use two CASE expressions:
SELECT
CASE WHEN 1 = 1 THEN 'A' ELSE 'C' END,
CASE WHEN 1 = 1 THEN 'B' ELSE 'D' END
You need to write separately.
SELECT
IF(1=1, 'A', 'C'),
IF(1=1, 'B', 'D')

MySQL Order By With Grades As String But Want Integer

I want to order grades that are a string in the following order.
K, 1, 2, 4, .... 12
But I keep getting 5, 4, 3, ... 12, K, 1
The grade column in sims_classroom is VARCHAR(255) and the table is latin1;
I have tried every cast and trick in the book. At the moment I have the following trick by adding 0 to it. What am I doing wrong?
SELECT
(SELECT district_get_name_function(sod.parent_id, sod.id)) AS 'district_name',
(SELECT school_get_name_function(so.id)) AS 'school_name',
st.teacher_username,
st.teacher_first_name,
st.teacher_last_name,
c.name as 'classroom_name',
c.grade,
c.id,
d.name AS 'discipline_name',
d.id AS 'discipline_id',
lc.name AS 'program_name',
lc.id AS 'program_id'
FROM sims_classroom c
.
.
.
ORDER BY
CASE lower(sort_direction) WHEN 'asc' THEN
CASE lower(sort_order)
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN 0
ELSE (c.grade + 0)
END
WHEN 'teachername' THEN lower(st.teacher_first_name)
ELSE c.name
END
END ASC,
CASE lower(sort_direction) WHEN 'desc' THEN
CASE lower(sort_order)
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN 10000
ELSE (c.grade + 0)
END
WHEN 'teachername' THEN lower(st.teacher_first_name)
ELSE c.name
END
END DESC
You could create a lookup table for the grades. It would have the Grade_Name (i.e. 'K','1','2', etc) and a Grade_Order as an int.
You'd have records like this:
Grade_Name Grade_Order
K 1
1 2
2 3
3 4
and so on.
Then you can add that lookup table to your JOIN and ORDER BY Grade_Order.
I could only get it to work doing this.
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN '00'
WHEN '9' THEN '09'
WHEN '8' THEN '08'
WHEN '7' THEN '07'
WHEN '6' THEN '06'
WHEN '5' THEN '05'
WHEN '4' THEN '04'
WHEN '3' THEN '03'
WHEN '2' THEN '02'
WHEN '1-2' THEN '01'
WHEN '1' THEN '01'
ELSE c.grade
END