use select case in Mysql - mysql

The question I try to solve:
Return the value for "prefix" following these conditions:
If model_hyouji is a number and ranging from 0 to 9, set prefix = 0
If model_hyouji is a letter and ranging from a to z or A to Z, set prefix = 1
In all other cases, set prefix = 2
I used this SQL:
SELECT model_code,
model_hyouji,
model_name_prefix,
model_kana_prefix,
model_count,
case prefix
when 'a' then 1
when 'b' then 2
else 3
end
FROM webikept.mst_model_v2
where model_maker_code = 1
and model_displacement between 51 and 125
and (SELECT substring(model_hyouji,1,1) as prefix
FROM webikept.mst_model_v2 )
and I get this error:
Unknown column 'prefix' in 'field list'

assuming you column model_hyouji is varchar(1) (otherwise use substr(model_hyouji,1) )
SELECT model_code,
model_hyouji,
model_name_prefix,
model_kana_prefix,
model_count,
case
when model_hyouji between '0' and '9' then 0
when model_hyouji between 'a' and 'z' then 1
when model_hyouji between 'A' and 'Z' then 1
else 2
end prefix
FROM webikept.mst_model_v2
where model_maker_code = 1
and model_displacement between 51 and 125
and (SELECT substring(model_hyouji,1,1) as prefix
FROM webikept.mst_model_v2 )
or you can use regexp
SELECT model_code,
model_hyouji,
model_name_prefix,
model_kana_prefix,
model_count,
case
when model_hyouji REGEXP '^[0-9]{1}$' then 0
when model_hyouji REGEXP '^[A-Za-z]$' then 1
else 2
end prefix
FROM webikept.mst_model_v2
where model_maker_code = 1
and model_displacement between 51 and 125
and (SELECT substring(model_hyouji,1,1) as prefix
FROM webikept.mst_model_v2 )

SELECT
model_code,model_hyouji,model_name_prefix,model_kana_prefix,model_count,
case
when prefix = 'a' then 1 when 'b' then 2 else 3 end
You need CASE WHEN prefix =
But you also dont specify which prefix column you want to use hence the error on unknown column
E.G
SELECT
model_code,model_hyouji,model_name_prefix,model_kana_prefix,model_count,
case
WHEN model_kana_prefix = 'a' then 1
WHEN model_kana_prefix = 'b' then 2
else 3 end

Related

How to find 7 consecutive non zero values in SQL?

If we have a table of 15 columns, the first one is id, and the other columns have numeric
data type,
in MySQL or a similar languages, how can I find if the record have 7 consecutive non zero values, meaning that 7 of the contiguous columns have a value not equals to zero?
We can write a query has a lot of OR operations to check that each 7 columns don't have 0 value, but I want to know if there is shorter way
Try the following using CONCAT and INSTR functions, explanation is within query comments:
/*
check if the col value is not equal to 0,
this will return 1 if true and 0 if false,
and concatenate all of the returned values.
*/
with concat_cols as
(
select *,
concat(
col1<>0, col2<>0, col3<>0, col4<>0, col5<>0,
col6<>0, col7<>0, col8<>0, col9<>0, col10<>0,
col11<>0, col12<>0, col13<>0, col14<>0, col15<>0
) as con_col
from table_name
)
/*
using the instr function, check if the concatenated
result contains 7 consecutive 1s (7 not 0 values).
*/
select * from concat_cols
where instr(con_col, repeat('1', 7))
See demo
One way:
field(0,col1,col2,col3,col4,col5,col6,col7) = 0 or
field(0,col2,col3,col4,col5,col6,col7,col8) = 0 or
field(0,col3,col4,col5,col6,col7,col8,col9) = 0 or
field(0,col4,col5,col6,col7,col8,col9,col10) = 0 or
field(0,col5,col6,col7,col8,col9,col10,col11) = 0 or
field(0,col6,col7,col8,col9,col10,col11,col12) = 0 or
field(0,col7,col8,col9,col10,col11,col12,col13) = 0 or
field(0,col8,col9,col10,col11,col12,col13,col14) = 0 or
field(0,col9,col10,col11,col12,col13,col14,col15) = 0
SELECT id
FROM your_table
WHERE SUM(CASE WHEN column_2 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_3 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_4 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_5 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_6 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_7 > 0 THEN 1 ELSE 0 END +
CASE WHEN column_8 > 0 THEN 1 ELSE 0 END) >= 7

Order a column in mysql by if it contains a letter

I have a column named convoys in my worker-database and I first want to sort the 'non-letter-containing'-values and after them the 'letter-containing' ones.
For example here are a few values
name
convoy
worker1
1
worker2
3
worker3
M 4
worker4
M5
worker5
4
worker6
11
and it should sort them like this
name
convoy
worker1
1
worker2
3
worker5
4
worker6
11
worker3
M 4
worker4
M5
Has anybody some kind of idea how to make this query working?
I think the most direct way to do that would be the following (using regular expression):
SELECT name,
convoy
FROM TABLE_NAME
ORDER BY CASE WHEN convoy REGEXP '^[0-9]+$' THEN convoy ELSE convoy END
Order by the first token combined from characters that are not digits or spaces, and then by the first token combined from digits (and converted to UNSIGNED).
Please note that this solution also order correctly strings such as 'M13' (which comes after 'M 4' and 'M5')
select *
from t
order by regexp_substr(convoy, '[^\\d\\s]+')
,cast(regexp_substr(convoy, '\\d+') as UNSIGNED)
fiddle
A maximal unsigned integer: 4294967295
MySQL 5.6
This SQL sorts 'non-letter-containing' values as numbers, then others.
select
name,
convoy
from Table1
order by
case when
convoy REGEXP '^[0-9]+$'
then convert(convoy, UNSIGNED INTEGER)
else 4294967295
end,
convoy
;
Or maybe better:
select
*
from Table1
order by
case when
convoy REGEXP '^[0-9]+$'
then LPAD(convert(convoy, UNSIGNED INTEGER),10,0)
else convoy
end
;
DDL:
CREATE TABLE Table1
(`name` varchar(7), `convoy` varchar(3))
;
INSERT INTO Table1
(`name`, `convoy`)
VALUES
('worker1', '1'),
('worker2', '3'),
('worker3', 'M 4'),
('worker4', 'M5'),
('worker5', '4'),
('worker6', '11')
;
Output:
name
convoy
worker1
1
worker2
3
worker5
4
worker6
11
worker3
M 4
worker4
M5

How to show positions of '1' within a long number mysql

I know I can find the first position of 1 with my number by using the following:
SELECT POSITION("1" IN "0000100001000001");
How would I find all the positions of 1 to return 5;10;16
Your string appears to be a 16-bit number represented in base-2.
I set a user variable to your example string.
set #bin = '0000100001000001';
We can use CONV() to convert it to a base-10 number instead of base-2. This allows the integer value to be used when we use it in numeric expressions.
mysql> select conv(#bin, 2, 10);
+-------------------+
| conv(#bin, 2, 10) |
+-------------------+
| 2113 |
+-------------------+
Then we can test for a particular bit set in this number using the & bitwise-and operator.
mysql> select conv(#bin, 2, 10) & 64;
+------------------------+
| conv(#bin, 2, 10) & 64 |
+------------------------+
| 64 |
+------------------------+
We can test all the bits of the integer value. If a given bit is set, then substitute the "position," as you call it, for that bit (counting from left to right, which is the opposite of the traditional bit positions).
If the bit is not set, then default to NULL. Then concatenate these together using CONCAT_WS(), which ignores NULLs.
select concat_ws(';',
case conv(#bin,2,10)&32768 when 32768 then 1 end,
case conv(#bin,2,10)&16384 when 16384 then 2 end,
case conv(#bin,2,10)&8192 when 8192 then 3 end,
case conv(#bin,2,10)&4096 when 4096 then 4 end,
case conv(#bin,2,10)&2048 when 2048 then 5 end,
case conv(#bin,2,10)&1024 when 1024 then 6 end,
case conv(#bin,2,10)&512 when 512 then 7 end,
case conv(#bin,2,10)&256 when 256 then 8 end,
case conv(#bin,2,10)&128 when 128 then 9 end,
case conv(#bin,2,10)&64 when 64 then 10 end,
case conv(#bin,2,10)&32 when 32 then 11 end,
case conv(#bin,2,10)&16 when 16 then 12 end,
case conv(#bin,2,10)&8 when 8 then 13 end,
case conv(#bin,2,10)&4 when 4 then 14 end,
case conv(#bin,2,10)&2 when 2 then 15 end,
case conv(#bin,2,10)&1 when 1 then 16 end) as bits_set;
Output:
+----------+
| bits_set |
+----------+
| 5;10;16 |
+----------+
There is no such functionality built in. You can create your own function for this.
delimiter $$
create function f_position_multiple(
in_f char(1),
in_str text
)
returns text
begin
declare v_delim char(1);
declare v_loc int;
declare v_ret text;
set v_ret = '';
set v_delim = '';
set v_loc = 0;
set v_loc = locate(in_f, in_str, v_loc+1);
while(v_loc>0) do
set v_ret = concat(v_ret, v_delim, v_loc);
set v_delim = ';';
set v_loc = locate(in_f, in_str, v_loc+1);
end while;
return v_ret;
end
$$
And then you can use:
select f_position_multiple('1', '1001001')
A solution for MySql 8.0+ with a recursive CTE:
set #n = '0000100001000001';
with recursive cte as (
select 0 pos, ' ' bit
union all
select pos + 1, substring(#n, pos + 1, 1)
from cte
where pos < length(#n)
)
select group_concat(pos order by pos separator ';') result
from cte
where bit = '1'
See the demo.
Result:
| result |
| ------- |
| 5;10;16 |

Sort values that contain letters and symbols in a custom order

Can you change the MySQL sort by function? I am trying to sort my values according to an arbitrary order.
Currently looking for ways to inject a function that might help me out here short of adding a column and modifying the import.
This is the order I want:
AAA
AA+
AA
AA-
A+
A
A-
BBB+
BBB
BBB-
BB+
BB
BB-
B+
B
B-
CCC+
CCC
CCC-
CC
This is my result using sort by:
A
A+
A-
AA
AA+
AA-
AAA
B
B+
B-
BB
BB+
BB-
BBB
BBB+
BBB-
C
CC
CCC
CCC+
CCC-
EDIT:
Attempting but getting syntax errors:
CREATE FUNCTION sortRating (s CHAR(20))
RETURNS INT(2)
DECLARE var INT
CASE s
WHEN 'AAA' THEN SET var = 1
WHEN 'AA+' THEN SET var = 2
ELSE
SET VAR = 3
END CASE
RETURN var
END;
This is possible using the following syntax:
ORDER BY FIELD(<field_name>, comma-separated-custom-order)
for instance, if the expression you want to order by is called rating, then your ORDER BY clause would read:
ORDER BY FIELD(rating, 'AAA', 'AA+', 'AA', 'AA-', 'A+', 'A', 'A-',
'BBB+', 'BBB', 'BBB-', 'BB+', 'BB', 'BB-',
'B+', 'B', 'B-', 'CCC+', 'CCC', 'CCC-', 'CC')
Here's documentation on the FIELD FUNCTION
I see a pattern here:
BBB+
BBB
BBB-
BB+
BB
BB-
B+
B
B-
Think of each character as a column and sort each column in this order:
Letters
+
empty string
-
SELECT rating
FROM test
ORDER BY
MID(rating, 1, 1),
CASE MID(rating, 2, 1) WHEN '+' THEN 2 WHEN '' THEN 3 WHEN '-' THEN 4 ELSE 1 END,
CASE MID(rating, 3, 1) WHEN '+' THEN 2 WHEN '' THEN 3 WHEN '-' THEN 4 ELSE 1 END,
CASE MID(rating, 4, 1) WHEN '+' THEN 2 WHEN '' THEN 3 WHEN '-' THEN 4 ELSE 1 END
SQL Fiddle

SQL statement equivalent to ternary operator

I would like to create a statement that is equivalent to (x - y == 0) ? return 0 : return 100 in MySQL. Something that might look like this:
SELECT id, [(integer_val - 10 == 0) ? 0 : 100] AS new_val FROM my_table
I want to compare an attribute in each row to a certain number, and if the difference between that number and the number in the row is 0, I want it to give me 0, otherwise, I want it to give me 100.
Example:
Applying this query on my_table (with 10 being the 'compared to' number):
id | integer_val
===================
1 10
2 10
3 3
4 9
Would return this:
id | new_val
===================
1 100
2 100
3 0
4 0
How can I do this?
Try this:
SELECT id, IF(integer_val = 10, 100, 0) AS new_val
FROM my_table;
OR
SELECT id, (CASE WHEN integer_val = 10 THEN 100 ELSE 0 END) AS new_val
FROM my_table;
Use case when statement:
select *, (case when integer_val = 10 then 100 else 0 end) as New_Val
from yourtable
Try using the IF function:
SELECT id, IF(integer_val - 10 = 0, 0, 100) AS new_val FROM my_table
(I stuck with your condition expression, but it can be simplified a bit since integer_value - 10 = 0 has exactly the same truth value as integer_value = 10.)
Note that the IF function is different from MySQL's IF statement used for stored programs.