MySql Group by with Pivot - mysql

I am having a table in mysql (say studentinfo).
SELECT * FROM StudentInfo;
I want the following output without using any extra or temporary table. (May be using group by and pivot)

You need to create a pivot table, here is a link with lots of good examples.
Essentially, your just gonna do something like this
SELECT Rollnumber,
property
CASE WHEN Property="Name" then Property end as Name,
CASE WHEN Property="Year" then Property end as Year,
CASE WHEN Property="City" then Property end as City,
FROM whatever_table
GROUP BY Rollnumber
You can modify this however you want, to get the results you desire.

This should do what you want:
select si.Rollnumber,
max(case when si.Property = 'Name' then si.Value end) as Name,
max(case when si.Property = 'Year' then si.Value end) as Year,
max(case when si.Property = 'City' then si.Value end) as City
from StudentInfo si
group by si.Rollnumber;

Try below:
select * from (SELECT A.Rollnumber,if(A.Property='Name',Value,
(select B.Value from StudentInfo B where B.Property='Name' and B.Rollnumber=A.Rollnumber LIMIT 1)) as Name,
if(Property='Year',Value,
(select B.Value from StudentInfo B where B.Property='Year' and B.Rollnumber=A.Rollnumber LIMIT 1)) as Year,
if(Property='City',Value,
(select B.Value from StudentInfo B where B.Property='City' and B.Rollnumber=A.Rollnumber LIMIT 1))
as City
FROM StudentInfo A) Temp group by Rollnumber

SELECT
name.rollnumber,
name.value AS name,
year.value AS year,
city.value AS city
FROM
StudentInfo name
INNER JOIN StudentInfo year ON name.rollnumber = year.rollnumber
INNER JOIN StudentInfo city ON name.rollnumber = city.rollnumber
WHERE
name.property = 'name' AND
year.property = 'year' AND
city.property = 'city' AND

Related

Return count 0 with mysql group by and where by date

I want to create a single query to result data like this:
but when I insert where clause, column name just result a few value from column m_ccode:
Q: how keep all name column values if I insert where clause?
Here the working fiddle:
http://sqlfiddle.com/#!9/687776/10
use MONTH(t.date) = '10' AND YEAR(t.date) = '2018' condition in on cluase like below
demo
SELECT ccode.name,IFNULL(count(DISTINCT u.username),0) as total_active
,(count(DISTINCT u.username) - count(DISTINCT t.username)) as total_non_active
from m_ccode as ccode
left join m_user as u on u.ccode = ccode.id
left join t_safety_act t on t.username = u.username
and MONTH(t.date) = '10' AND YEAR(t.date) = '2018' group by ccode.id;

MySQL with multiple SELECT and GROUP BY

I have a problem with my database in mysql. I would like to have a table from my database with date, pat, dureeP, dureeC but this function doesn't GROUP BY :
select *
from (SELECT date_format(p.date, "%Y-%m") AS date
,p.pat
,AVG(a) AS dureeP
FROM timing as t, patient as p
WHERE t.id_p = p.id_p
AND t.pos=6
AND t.heure_fin IS NOT NULL
GROUP BY p.pat, MONTH(p.date), YEAR(p.datede)
) as T1,
(SELECT AVG(b) AS dureeC
FROM timing as t, patient as p
WHERE t.id_p = p.id_p
AND t.pos=3
AND t.heure_fin IS NOT NULL
GROUP BY p.pathologie, MONTH(p.date), YEAR(p.date)
) as T2
With one SELECT I can have what I want but with multiple SELECT I can Group By.
Do you have an idea?
Thank you
To simplify your query you might be able to use "conditional aggregates" which basically means placing a case expression inside an aggregate function
SELECT
p.pathologie
, MONTH(p.date)
, YEAR(p.date)
, AVG(CASE WHEN t.pos = 3 THEN b END) AS dureeC
, AVG(CASE WHEN t.pos = 6 THEN a END) AS dureeP
FROM timing AS t
INNER JOIN patient AS p ON t.id_p = p.id_p
WHERE t.heure_fin IS NOT NULL
GROUP BY
p.pathologie
, MONTH(p.date)
, YEAR(p.date)

SQL query to combine total of two fields

I ought to combine two result fields based on my requirement. For example, below query provides the result as shown. But I need a case statement that states that both 'wind' and 'wind c' are the same, hence combine its total.
SELECT result, COUNT(*) AS total from(
SELECT t.Id AS Id,
CASE
WHEN LTRIM(RTRIM(AC)) = ' ' THEN AG
WHEN LOWER(AC) IS NOT NULL THEN LOWER(AC)
ELSE LOWER(AG)
END AS result,MaxDate,
FROM [DC_20160601] t
INNER JOIN ( SELECT Id, MAX(DateTime) AS MaxDate
FROM [DC_20160601]
GROUP BY Id) tm
ON t.Id = tm.Id AND t.DateTime = tm.MaxDate)
GROUP BY result
Current Result:
Result Total
Wind 1212
Wind c 345
sqrim 321
sqrim mob 123
Expected Result:
Result Total
Wind mobile 1557
Sqrim mobile 444
You can select the first word in a string via substring_index
SELECT SUBSTRING_INDEX(`result`, ' ', 1);
Now group by the first word of result
SELECT SUBSTRING_INDEX(`result`, ' ', 1), COUNT(*) AS total from(
SELECT t.Id AS Id,
CASE
WHEN LTRIM(RTRIM(AC)) = ' ' THEN AG
WHEN LOWER(AC) IS NOT NULL THEN LOWER(AC)
ELSE LOWER(AG)
END AS result,MaxDate,
FROM [DC_20160601] t
INNER JOIN ( SELECT Id, MAX(DateTime) AS MaxDate
FROM [DC_20160601]
GROUP BY Id) tm
ON t.Id = tm.Id AND t.DateTime = tm.MaxDate)
GROUP BY SUBSTRING_INDEX(`result`, ' ', 1)
You might try to extract everything before the first space and use this for grouping:
SUBSTRING_INDEX(result, ' ', 1)
Otherwise you need to maintain a lookup table to match multiple variations to a single result.
You can add the case statements as an outer query. Assuming that your query returns the Current Result that you posted, here is an example of the needed case statements:
select
case
when a.result = 'Wind' or a.result = 'Wind c' then 'Wind mobile'
else
case
when a.result = 'sqrim' or a.result = 'sqrim mob'
then 'Squirm mobile'
end
end as res,
sum(total)
from
(
SELECT result, COUNT(*) AS total from(
SELECT t.Id AS Id,
CASE
WHEN LTRIM(RTRIM(AC)) = ' ' THEN AG
WHEN LOWER(AC) IS NOT NULL THEN LOWER(AC)
ELSE LOWER(AG)
END AS result,MaxDate,
FROM [DC_20160601] t
INNER JOIN ( SELECT Id, MAX(DateTime) AS MaxDate
FROM [DC_20160601]
GROUP BY Id) tm
ON t.Id = tm.Id AND t.DateTime = tm.MaxDate)
GROUP BY result
) a
group by res
It would be best to have the values in the case statements specified in a lookup table and to get them from there or you can just add additional ones as case statements if needed but it's not ideal...
Hope this helps!

SQL order by multiple condition

I have a table with 'name','status'-fail or success,'counts'- 1 to 100. I want to order it in such a way that names of only 'fail' should show on top together, then same name with fail and success together, then names with only success together.
Can we do it sql query language ?
Thank you.
Ok, this should work on most RDBMS:
SELECT A.*
FROM YourTable A
INNER JOIN (SELECT name,
COUNT(DISTINCT status) StatusCount,
MIN(status) MinStatus
FROM YourTable
GROUP BY name) B
ON A.name = B.name
ORDER BY CASE WHEN StatusCount = 1 AND MinStatus = 'fail' THEN 1
WHEN StatusCount = 2 THEN 2
ELSE 3 END, A.name, A.status
If it is MySQL
select *, 0 as o
from t
union all
select *, 1 as o
from t
order by
o = 1 and status != 'fail', o != 1, status = fail

SQL Joins to Get Monthly Total Wages from Three Tables

I need to get empolyees info from employees table, and their total wages from two different tables.
The SQL is approximately like this, but I don't really know how to use joins to do this:
CONCAT(first_name, ' ', last_name) from employees as e
Sum(hours*pay) where date is "THIS MONTH" and employee_id = e.id from taxed_work
Sum(hours*pay) where date is "THIS MONTH" and employee_id = e.id from nontaxed_work
I am not sure how to join these together properly. I don't want to see any of the employees that have not done either kind of work for the month, only those who have. I'm using mysql and will put the data in a table with php
If anyone could tell me how to do the "THIS MONTH" part that would be cool too. Just being lazy on that part, but figured while I was here...
Thanks for the help!
You could use correlated subqueries:
select concat(first_name, ' ', last_name)
, (
select sum(hours*pay)
from taxed_work tw
where tw.employee_id = e.id
and year(tw.date) = year(now())
and month(tw.date) = month(now())
)
, (
select sum(hours*pay)
from nontaxed_work ntw
where ntw.employee_id = e.id
and year(ntw.date) = year(now())
and month(ntw.date) = month(now())
)
from employees e
You can calculate their totals inside subquery.
SELECT a.id ,
CONCAT(first_name, ' ', last_name) FullName,
b.totalTax,
c.totalNonTax,
FROM employees a
LEFT JOIN
(
SELECT employee_id, Sum(hours*pay) totalTax
FROM taxed_work
WHERE DATE_FORMAT(`date`,'%c') = DATE_FORMAT(GETDATE(),'%c')
GROUP BY employee_id
) b ON b.employee_id = a.id
LEFT JOIN
(
SELECT employee_id, Sum(hours*pay) totalTax
FROM nontaxed_work
WHERE DATE_FORMAT(`date`,'%c') = DATE_FORMAT(GETDATE(),'%c')
GROUP BY employee_id
) c ON c.employee_id = a.id
Try this query.
select
CONCAT(first_name, ' ', last_name) as employee_name,
sum(case when t.this_date = 'this_month' then t.hours*t.pay else 0 end),
sum(case when n.this_date = 'this_month' then t.hours*t.pay else 0 end)
from employees e
left join taxed_work t on e.id = t.employee_id
left join nontaxed_work n on e.id = n.employee_id
group by (first_name, ' ', last_name)
Please replace the t.this_date and n.this_date fields with actual field names as I am not aware of the exact table structure. Also, replace the "this_month" value as per your need.