mysql combining two tables to produce the following output - mysql

hello i had ask the same question before but i want another way. we can use locate and max function to solve the question. but my teacher told me to do like this
my code is like this when '0' then '1' else '0'
select u.id, u.name,
case f.finger when '0' then '1' else '0' end as '0',
case f.finger when '1' then '1' else '0' end as '1',
case f.finger when '2' then '1' else '0' end as '2',
case f.finger when '3' then '1' else '0' end as '3',
case f.finger when '4' then '1' else '0' end as '4',
case f.finger when '5' then '1' else '0' end as '5'
from users u left join user_fingerprints f
on u.id= f.user_id
the code above will resulted in 8 rows.
then i need to combine the rows so that the rows with the same id combine to produce this
from that result then use case function. when the value is 1 then y. when value is zero then n.
can someone give me the answer without the use of max function? thanks
the table and result

You can also do it with SUM() and another CASE EXPRESSION :
SELECT t.id,t.name,
CASE WHEN t.`0` > 0 THEN 'Y' ELSE 'N' as `0`
CASE WHEN t.`1` > 0 THEN 'Y' ELSE 'N' as `1`
....
FROM (
SELECT u.id,u.name,
SUM(CASE WHEN f.finger = '0' then '1' else '0' end) as `0`,
SUM(CASE WHEN f.finger = '1' then '1' else '0' end) as `1`,
....
from users u left join user_fingerprints f
on u.id= f.user_id
GROUP BY u.id,u.name) t

Related

Case statement not working with or condition

Please help me with this code.
SELECT (CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN ('7' OR '8') THEN 'SA'
END) `REGION`,
This is the result:
Region
null
MM
The result should be like this:
Region
SA
MM
The following syntax is not valid:
WHEN ('7' OR '8') THEN 'SA'
What follows WHEN or ELSE using this style of CASE expression can only be a literal value, not a logical expression. So, you could refactor to:
SELECT
CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN '7' THEN 'SA' -- repeat the 'SA' predicate twice
WHEN '8' THEN 'SA' END AS REGION
FROM yourTable;
If you wanted to combine the 7 and 8 cases in a single WHEN, then you would have to use the longer form of CASE:
SELECT
CASE WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) = '7' OR
LEFT(BRANCH_CODE, 1) = '8' THEN 'SA' END AS REGION
FROM yourTable;
This second version is fairly ugly IMHO, and I would probably stick with the first version, which just repeats the SA predicate in two places.
I had similar issues when trying to apply multiple condition statements in "CASE" statement.
I solved it by moving the test after the "WHEN" statement as following :
SELECT (CASE
WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) IN ('7' OR '8') THEN 'SA'
END) `REGION`,

MySQL: Case Query within a Case Query?

I have a query that gets unit count and it tagging if completed or not.
SELECT distinct location,
case when id is NULL then 'Not Started'
when '1' then 'Completed'
else 'In Progress' end as Remarks,
count(name) as CountName
FROM table
group by location,
case when id is NULL then 'Not Started'
when '1' then 'Completed'
else 'In Progress' end;
Result:
But I want to summarized this as below image:
Condition is when there are more that two(2) Remarks in Location it should be tagged as "In-progress" and sum the CountName. But when only one Remarks for a Location, gets the Remarks as its tagged.
Not sure on this (sample data would help), but try this:
SELECT Location,
case when count(id) > 1 then 'In Progress'
when max(id) is null then 'Not Started'
when max(id) = 1 then 'Completed'
else 'In Progress' end As Remarks,
count(name) as CountName
FROM table
GROUP BY location
Like you said, a case within a case:
select location,
case when count(distinct case when id is null then 'Not Started'
when id = '1' then 'Completed'
else 'In Progress' end) > 1
then 'In Progress'
else max(case when id is null then 'Not Started'
when id = '1' then 'Completed'
else 'In Progress' end)
end as remarks,
count(*) as CountName
from tbl
group by location
SQLFiddle Demo
Try This query:-
SELECT location,
if(count(1) > 1, 'In Progress', Remarks) Remarks,
sum(countName) countName
FROM location
group by location

mysql join the 2 tables to produce following output

I have two tables: users and user_fingerprints.
How do I combine the two tables to produce the output?
I tried
select u.id, u.name,
case f.finger (when 0 then 'y' else 'n' end) '0',
case f.finger (when 1 then 'y' else 'n' end) '1',
case f.finger (when 2 then 'y' else 'n' end) '2',
case f.finger (when 3 then 'y' else 'n' end) '3',
case f.finger (when 4 then 'y' else 'n' end) '4',
case f.finger (when 5 then 'y' else 'n' end) '5',
case f.finger (when 6 then 'y' else 'n' end) '6'
from user u left join user_fingerprint f
on u.id=f.user_id
group by u.id
but the result will only take one row from same id and update it in the output table. when i use max function, it worked, but is there any way without using max?
Use an aggregation function:
select u.id, u.name,
max(case f.finger when 0 then 'y' else 'n' end) as '0',
max(case f.finger when 1 then 'y' else 'n' end) as '1',
max(case f.finger when 2 then 'y' else 'n' end) as '2',
max(case f.finger when 3 then 'y' else 'n' end) as '3',
max(case f.finger when 4 then 'y' else 'n' end) as '4',
max(case f.finger when 5 then 'y' else 'n' end) as '5',
max(case f.finger when 6 then 'y' else 'n' end) as '6'
from user u left join
user_fingerprint f
on u.id = f.user_id
group by u.id;
I would suggest that you reconsider using integers as column aliases. Looks doomed to be confusing . . . or worse, to cause hard to spot errors.
Also, note that max() works because 'y' > 'n'. There are other methods if you don't want to depend on that.
This also assumes that you want one summary row for each column. Otherwise you might want something like group_concat().
Not sure why don't you want to use function max, without max I think you can do it like this:
SELECT
u.id, u.name,
CASE WHEN LOCATE('0', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `0`,
CASE WHEN LOCATE('1', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `1`,
CASE WHEN LOCATE('2', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `2`,
CASE WHEN LOCATE('3', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `3`,
CASE WHEN LOCATE('4', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `4`,
CASE WHEN LOCATE('5', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `5`,
CASE WHEN LOCATE('6', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `6`
FROM USER u
LEFT JOIN user_fingerprint f ON u.id = f.user_id
GROUP BY u.id
GROUP_CONCAT will concat all finger for each user and separated by comma, then LOCATE will return the index of first parameter in second parameter.

mysql pivot dynamic tables and return only where count > 0

I have a query with this count cases that I use to pivot some totals based on case. This is the query:
$user_attrib = some_value;
$user_size = some_value;
$items = [218, 219];
$items = join(",", $items);
SELECT owned_items.model_id,
Count(owned_items.model_size_id) AS total_owned,
makes.make,
items.model_name,
items.picture,
items.color,
items.material,
Count(CASE item_sizes.id WHEN '1' THEN item_sizes.id ELSE NULL END) AS '1',
Count(CASE item_sizes.id WHEN '2' THEN item_sizes.id ELSE NULL END) AS '2',
Count(CASE item_sizes.id WHEN '3' THEN item_sizes.id ELSE NULL END) AS '3',
Count(CASE item_sizes.id WHEN '4' THEN item_sizes.id ELSE NULL END) AS '4',
Count(CASE item_sizes.id WHEN '5' THEN item_sizes.id ELSE NULL END) AS '5',
Count(CASE item_sizes.id WHEN '6' THEN item_sizes.id ELSE NULL END) AS '6',
Count(CASE item_sizes.id WHEN '7' THEN item_sizes.id ELSE NULL END) AS '7',
Count(CASE item_sizes.id WHEN '8' THEN item_sizes.id ELSE NULL END) AS '8',
Count(CASE item_sizes.id WHEN '9' THEN item_sizes.id ELSE NULL END) AS '9',
Count(CASE item_sizes.id WHEN '10' THEN item_sizes.id ELSE NULL END) AS '10',
Count(CASE item_sizes.id WHEN '11' THEN item_sizes.id ELSE NULL END) AS '11',
Count(CASE item_sizes.id WHEN '12' THEN item_sizes.id ELSE NULL END) AS '12',
Count(CASE item_sizes.id WHEN '13' THEN item_sizes.id ELSE NULL END) AS '13',
Count(CASE item_sizes.id WHEN '14' THEN item_sizes.id ELSE NULL END) AS '14',
Count(CASE item_sizes.id WHEN '15' THEN item_sizes.id ELSE NULL END) AS '15'
FROM owned_items
INNER JOIN owned_item_user
ON owned_items.id = owned_item_user.owned_item_id
INNER JOIN users
ON owned_item_user.user_id = users.id
INNER JOIN item_sizes
ON owned_items.model_size_id = item_sizes.id
INNER JOIN items
ON owned_items.model_id = items.id
INNER JOIN makes
ON owned_items.make_id = makes.id
WHERE users.attrib_id = $user_attrib
AND users.size_id = $user_size
AND owned_items.model_id IN ($items)
GROUP BY owned_items.model_id
I'd like to generalize the data so that if I add a 16th case I don't have to manually add another line and I would like to return only cases that have results > 0.
For the first part I tried with this pivot dynamic tables adapting code without success. Second part I tried to set HAVING Count(CASE item_sizes.id WHEN '1' THEN item_sizes.id ELSE NULL END) AS '1' > 0 (etc..) without success either.
You can use Group By + Count
Select item_sizes.id, count(*) from item_sizes where item_sizes.id between 1 and 15 group by item_sizes.id;

MySQL - Extract datetime and convert into matrix mapping

I have huge amount of MySQL record data and must be tranformed like this :
My question is, how to extract datetime value (month, week, hour) and insert it into exact column with binary value (0 or 1) as image above.
PROBLEM SOLVED, i just figured out the easiest way, here for the example:
UPDATE TABLE
SET h1 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '1' THEN 1
ELSE '0'
END
, h2 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '2' THEN '1'
ELSE '0'
END
, h3 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '3' THEN '1'
ELSE '0'
END
, h4 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '4' THEN '1'
ELSE '0'
END
, h5 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '5' THEN '1'
ELSE '0'
END
, h6 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '6' THEN '1'
ELSE '0'
END
, h7 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '7' THEN '1'
ELSE '0'
END
;
PROBLEM SOLVED, i just figured out the easiest way, here for the example:
UPDATE TABLE
SET h1 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '1' THEN 1
ELSE '0'
END
, h2 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '2' THEN '1'
ELSE '0'
END
, h3 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '3' THEN '1'
ELSE '0'
END
, h4 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '4' THEN '1'
ELSE '0'
END
, h5 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '5' THEN '1'
ELSE '0'
END
, h6 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '6' THEN '1'
ELSE '0'
END
, h7 = CASE WHEN (SELECT DAYOFWEEK (trx_datetime)) = '7' THEN '1'
ELSE '0'
END
;