mysql join the 2 tables to produce following output - mysql

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.

Related

Count each day with SQL query

I want to display a table with SQL query like this:
I have run my query:
select
tb_r_orderdata.finishtime as date ,
count(*)sum all,
sum(when status = 'SUCCESS' and issync = '1' then 1 else 0 end) sumpaid,
sum(when status = 'SUCCESS' and issync in ('3', '4') then 1 else 0 end) sumfail,
sum(when status = 'CLOSED' then 1 else 0 end) sumclose,
sum(when status = 'Null' then 1 else 0 end) sumunflag
from
tb_r_orderdata;
But when I execute it, the result is different than what I expected. The result is like this:
Thank you for any help
You are missing the GROUP BY and the CASE:
select tb_r_orderdata.finishtime as date ,
COUNT(*) as sumall,
SUM(CASE WHEN status='SUCCESS' AND issync='1' then 1 ELSE 0 END) as sumpaid,
SUM(CASE WHEN status='SUCCESS' AND issync in ('3','4') then 1 ELSE 0 END) as sumfail,
SUM(CASE WHEN status='CLOSED' then 1 ELSE 0 END) as sumclose,
SUM(CASE WHEN status is null then 1 ELSE 0 END) as sumunflag
from tb_r_orderdata
group by tb_r_orderdata.finishtime ;
MySQL treats booleans as integers in a numeric context, with "1" for true and "0" for false. You can simplify your query to:
select o.finishtime as date ,
COUNT(*) as sumall,
SUM(status = 'SUCCESS' AND issync = '1') as sumpaid,
SUM(status = 'SUCCESS' AND issync in ('3', '4')) as sumfail,
SUM(status = 'CLOSED') as sumclose,
SUM(status is null) as sumunflag
from tb_r_orderdata o
where tb_r_orderdata.finishtime is not NULL
group by o.finishtime ;
This also removes NULL finish times.
Explanation in comment for Gordon Linoff
i have try your answer but there is record NULL in the top of table, i dont know why, can you explain it
with little bit change from Gordon Linoff answer
select tb_r_orderdata.finishtime as date ,
SUM(CASE WHEN status='SUCCESS' AND issync='1' then 1 ELSE 0 END) as sumpaid,
SUM(CASE WHEN status='SUCCESS' AND issync in ('3','4') then 1 ELSE 0 END) as sumfail,
SUM(CASE WHEN status='CLOSED' then 1 ELSE 0 END) as sumclose,
SUM(CASE WHEN status='NULL' then 1 ELSE 0 END) as sumunflag
from tb_r_orderdata
group by tb_r_orderdata.finishtime

mysql combining two tables to produce the following output

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

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 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;

Compare columns from SUM(CASE...END) in the same query

I'm trying to add a column named Ready to my query that checks if the sum of Complete is = to the sum of Total and places 'Y' if True and 'N' if FALSE.
Here is my query that works producing 4 columns
SELECT pc.Sub,
SUM(CASE WHEN `SheetStatus` LIKE 'Complete' THEN 1 ELSE 0 END) AS 'Complete',
SUM(CASE WHEN `SheetStatus` LIKE 'Not started' THEN 1 ELSE 0 END) AS 'Not Started',
SUM(CASE WHEN `CheckSheet` LIKE '%' THEN 1 ELSE 0 END) AS 'Total'
FROM `pc`
Group By pc.Sub WITH ROLLUP
I just cant figure out how to create the extra column if it is possible at all.
Regards
Try outer SELECT
SELECT `Complete`,
`Not Started`,
`Total`,
CASE WHEN `Complete` = `Total` THEN 'Y' ELSE 'N' END `Ready`
FROM (
SELECT pc.Sub,
SUM(CASE WHEN `SheetStatus` LIKE 'Complete' THEN 1 ELSE 0 END) AS `Complete`,
SUM(CASE WHEN `SheetStatus` LIKE 'Not started' THEN 1 ELSE 0 END) AS `Not Started`,
SUM(CASE WHEN `CheckSheet` LIKE '%' THEN 1 ELSE 0 END) AS `Total`
FROM `pc`
GROUP BY pc.Sub WITH ROLLUP) t
Try this:
SELECT pc.Sub,
SUM(IF(`SheetStatus`='Complete',1,0) AS 'Complete',
SUM(IF(`SheetStatus`='Not started',1,0) AS 'Not Started',
SUM(IF(`CheckSheet` LIKE '%',1,0) AS 'Total'
IF(SUM(IF(`CheckSheet` LIKE '%',1,0) = SUM(IF(`SheetStatus`='Complete',1,0),"Y","N") AS Ready
FROM `pc`
Group By pc.Sub WITH ROLLUP