MySQL get all users, whether or not they have any hours? - mysql

Trying to get all users, whether or not they have any hours? My LEFT OUTER JOIN still not working..
SELECT tblleaverequest.lqUser,
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 1 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jan',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 2 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Feb',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 3 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Mar',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 4 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Apr',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 5 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'May',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 6 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jun',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 7 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jul',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 8 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Aug',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 9 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Sep',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 10 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Oct',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 11 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Nov',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 12 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Dec',
SUM(tblleaverequest.lqHoursPL) AS PaidLeaveTotal
FROM tblusers LEFT OUTER JOIN tblleaverequest ON tblleaverequest.lqUser = tblusers.username
WHERE (tblusers.clr_accrual = '1') AND (YEAR(tblleaverequest.lqStartDate) = YEAR(CURDATE()))
GROUP BY tblusers.username
Here are my results, but I need to have the rest of the users w/o hours too.

Not sure about you db schema, but seem you just can move one condition from WHERE to ON clause
SELECT tblusers.username,
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 1 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jan',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 2 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Feb',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 3 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Mar',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 4 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Apr',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 5 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'May',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 6 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jun',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 7 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Jul',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 8 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Aug',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 9 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Sep',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 10 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Oct',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 11 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Nov',
SUM(CASE WHEN DATE_FORMAT(tblleaverequest.lqStartDate, '%m') = 12 THEN (tblleaverequest.lqHoursPL) ELSE 0 END) AS 'Dec',
SUM(tblleaverequest.lqHoursPL) AS PaidLeaveTotal
FROM tblusers
LEFT OUTER JOIN tblleaverequest
ON tblleaverequest.lqUser = tblusers.username
AND (YEAR(tblleaverequest.lqStartDate) = YEAR(CURDATE()))
WHERE (tblusers.clr_accrual = '1')
GROUP BY tblusers.username

WHERE ... (YEAR(tblleaverequest.lqStartDate) = YEAR(CURDATE()))
If there are no matching in records tblLeaveRequest, the date will be null. Since a null cannot equal anything, those records will be dropped. So you are essentially converting the OUTER JOIN to an INNER JOIN. Move that comparison to the JOIN statement to preserve the OUTER JOIN.
Update:
Be sure to grab the username from tblusers, since the tblleaverequest.lqUser value may be null due to the OUTER JOIN.
SELECT tblusers.username
, SUM(CASE ......)) AS Jan
, ....

Related

how to write mysql query with join and conditional sum with 3 tables

I have 3 mysql tables which saves invoice, invoice content and payment
inv_head(invno,invtot,invgtot)
inv_body(invno,typeid,qty,rate,linetot)
payment(invno,pay_amount,pay_method)
select inv_head.invno,inv_head.invgtot,
sum(CASE WHEN payment.pay_method='CASH' THEN payment.pay_amount ELSE 0 END) AS pay_cash,
sum(CASE WHEN payment.pay_method='CHEQUE' THEN payment.pay_amount ELSE 0 END) AS pay_chq
from inv_head left JOIN payment on inv_head.invno=payment.invno
where invdate between '2019-07-21 00:00:00' and '2019-07-21 23:00:00'
and unprodid=0
GROUP by inv_head.invno
returns below which is correct
invno invgtot pay_cash pay_chq
20190721-173208-9 242.5 100 100
20190721-174752-9 52 20 10
select inv_head.invno,inv_head.invtot,inv_head.invgtot,
sum(CASE WHEN inv_body.typeid=1 THEN inv_body.line_tot ELSE 0 END) AS stdsaletot,
sum(CASE WHEN inv_body.typeid=2 THEN inv_body.line_tot ELSE 0 END) AS rettot,
sum(CASE WHEN inv_body.typeid=3 THEN inv_body.line_tot ELSE 0 END) AS dmgtot,
sum(CASE WHEN inv_body.typeid=4 THEN (inv_body.qty * inv_body.rate)ELSE 0 END) AS fitot
from inv_head,inv_body
where invdate between '2019-07-21 00:00:00' and '2019-07-21 23:00:00'
and unprodid=0 and inv_head.invno=inv_body.invno
GROUP by inv_head.invno
returns below which is correct
invno invtot invgtot stdsaletot rettot dmgtot fitot
20190721-173208-9 242.5 242.5 242.5 0 0 0
20190721-174752-9 52 52 291 -168 -71 0
but when i combine above 2 queries,
select inv_head.invno,inv_head.invtot,inv_head.invgtot,
sum(CASE WHEN payment.pay_method='CASH' THEN payment.pay_amount ELSE 0 END) AS pay_cash,
sum(CASE WHEN payment.pay_method='CHEQUE' THEN payment.pay_amount ELSE 0 END) AS pay_chq,
sum(CASE WHEN inv_body.typeid=1 THEN inv_body.line_tot ELSE 0 END) AS stdsaletot,
sum(CASE WHEN inv_body.typeid=2 THEN inv_body.line_tot ELSE 0 END) AS rettot,
sum(CASE WHEN inv_body.typeid=3 THEN inv_body.line_tot ELSE 0 END) AS dmgtot,
sum(CASE WHEN inv_body.typeid=4 THEN (inv_body.qty * inv_body.rate)ELSE 0 END) AS fitot
from inv_body,inv_head left JOIN payment on inv_head.invno=payment.invno
where invdate between '2019-07-21 00:00:00' and '2019-07-21 23:00:00'
and unprodid=0 and inv_head.invno=inv_body.invno
GROUP by inv_head.invno
returns below result which is erroneous
invno invtot invgtot pay_cash pay_chq stdsaletot rettot dmgtot fitot
20190721-173208-9 242.5 242.5 100 100 727.5 0 0 0
20190721-174752-9 52 52 80 40 873 -504 -213 0
Your join works properly on payment and inv_head but it is not working on inv_body because you did not provided how to join inv_body with other tables
Try this hope will help you
SELECT inv_head.invno,inv_head.invtot,inv_head.invgtot,
SUM(CASE WHEN payment.pay_method='CASH' THEN payment.pay_amount ELSE 0 END) AS pay_cash,
SUM(CASE WHEN payment.pay_method='CHEQUE' THEN payment.pay_amount ELSE 0 END) AS pay_chq,
SUM(CASE WHEN inv_body.typeid=1 THEN inv_body.line_tot ELSE 0 END) AS stdsaletot,
SUM(CASE WHEN inv_body.typeid=2 THEN inv_body.line_tot ELSE 0 END) AS rettot,
SUM(CASE WHEN inv_body.typeid=3 THEN inv_body.line_tot ELSE 0 END) AS dmgtot,
SUM(CASE WHEN inv_body.typeid=4 THEN (inv_body.qty * inv_body.rate)ELSE 0 END) AS fitot
FROM payment RIGHT JOIN inv_head ON inv_head.invno=payment.invno
WHERE invdate BETWEEN '2019-07-21 00:00:00' AND '2019-07-21 23:00:00'
AND unprodid=0 LEFT JOIN inv_body ON inv_head.invno=inv_body.invno
GROUP BY inv_head.invno

How to convert this MySQL query to Eloquent?

I am trying to convert a raw SQL query into eloquent and I am struggling with the join part as it gets quite complex.
I have got as far as the joins but I am looking at the documentation and struggling to work out how to convert the rest.
Here is the raw query
SELECT
SUM(CASE WHEN t2.field_2 = 1 THEN 1 ELSE 0 END) AS 'lead',
SUM(CASE WHEN t2.field_2 = 2 THEN 1 ELSE 0 END) AS 'in_review',
SUM(CASE WHEN t2.field_2 = 3 THEN 1 ELSE 0 END) AS 'pre_app_sent',
SUM(CASE WHEN t2.field_2 = 4 THEN 1 ELSE 0 END) AS 'pre_app_back',
SUM(CASE WHEN t2.field_2 = 5 THEN 1 ELSE 0 END) AS 'pre_app_ok',
SUM(CASE WHEN t2.field_2 = 6 THEN 1 ELSE 0 END) AS 'awaiting_kyc',
SUM(CASE WHEN t2.field_2 = 7 THEN 1 ELSE 0 END) AS 'kyc_complete',
SUM(CASE WHEN t2.field_2 = 8 THEN 1 ELSE 0 END) AS 'awaiting_full_app_data',
SUM(CASE WHEN t2.field_2 = 9 THEN 1 ELSE 0 END) AS 'full_app_sent',
SUM(CASE WHEN t2.field_2 = 10 THEN 1 ELSE 0 END) AS 'merchant_live'
FROM leads l
JOIN (SELECT
ae.id,
ae.model_id,
ae.fields,
TRIM(BOTH '"' FROM SUBSTRING_INDEX(SUBSTRING_INDEX(ae.fields,';', 1), ':', -1)) AS field_1,
TRIM(BOTH '"' FROM SUBSTRING_INDEX(SUBSTRING_INDEX(ae.fields,';', 2), ':', -1)) AS field_2,
ae.created_at
FROM action_events ae) t2
ON l.id = t2.model_id
WHERE t2.created_at >= '2019-01-01 00:00:00'
AND t2.created_at <= '2019-01-31 23:59:59'
And here is as far as I got with converting it to eloquent
$query->select(
DB::raw('SUM(CASE WHEN t2.field_2 = 1 THEN 1 ELSE 0 END) AS "lead"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 2 THEN 1 ELSE 0 END) AS "in_review"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 3 THEN 1 ELSE 0 END) AS "pre_app_sent"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 4 THEN 1 ELSE 0 END) AS "pre_app_back"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 5 THEN 1 ELSE 0 END) AS "pre_app_ok"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 6 THEN 1 ELSE 0 END) AS "awaiting_kyc"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 7 THEN 1 ELSE 0 END) AS "kyc_complete"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 8 THEN 1 ELSE 0 END) AS "awaiting_full_app_data"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 9 THEN 1 ELSE 0 END) AS "full_app_sent"'),
DB::raw('SUM(CASE WHEN t2.field_2 = 10 THEN 1 ELSE 0 END) AS "merchant_live"'));

aggregating values by month, Group by statement in mysql

I have a question on how to group the following statement into months.
Database is MYSQL
Desired result is:
DRNAME, Jan, Feb, Mar, April, May ,June
SISHEN, 0, 0, 100, 250, 450, 500, 0
Result I get is:
DRNAME, Jan, Feb, Mar, April, May ,June
SISHEN, 0, 0, 100, 0, 0, 0,0
SISHEN, 0, 0,0,250,0,0,0
SISHEN, 0, 0, 0,0 , 450, 0, 0
query is
select drname,
case when month(loaddate) = 1 then sum(drvalue) end as 'Jan',<br>
case when month(loaddate) = 2 then sum(drvalue) end as 'Feb',<br>
case when month(loaddate) = 3 then sum(drvalue) end as 'March',<br>
case when month(loaddate) = 4 then sum(drvalue) end as 'April',<br>
case when month(loaddate) = 5 then sum(drvalue) end as 'May',<br>
case when month(loaddate) = 6 then sum(drvalue) end as 'June'<br>
from tblloadschedule<br>
where cancelloadflag = 'N' and drname like 'sish%'<br>
group by drname,month(loaddate)
You need to remove month(loaddate) from the group by clause and then use conditional aggregation instead:
select drname,
sum(case when month(loaddate) = 1 then drvalue else 0 end) as 'Jan',
sum(case when month(loaddate) = 2 then drvalue else 0 end) as 'Feb',
sum(case when month(loaddate) = 3 then drvalue else 0 end) as 'March',
sum(case when month(loaddate) = 4 then drvalue else 0 end) as 'April',
sum(case when month(loaddate) = 5 then drvalue else 0 end) as 'May',
sum(case when month(loaddate) = 6 then drvalue else 0 end) as 'June'
from tblloadschedule
where cancelloadflag = 'N' and drname like 'sish%'
group by drname
Modify your query to take aggregates of the conditional CASE expressions:
SELECT
drname,
SUM(CASE WHEN MONTH(loaddate) = 1 THEN drvalue END) AS Jan,
SUM(CASE WHEN MONTH(loaddate) = 2 THEN drvalue END) AS Feb,
SUM(CASE WHEN MONTH(loaddate) = 3 THEN drvalue END) AS March,
SUM(CASE WHEN MONTH(loaddate) = 4 THEN drvalue END) AS April,
sum(CASE WHEN MONTH(loaddate) = 5 THEN drvalue END) AS May,
sum(CASE WHEN MONTH(loaddate) = 6 THEN drvalue END) AS June
FROM tblloadschedule
WHERE
cancelloadflag = 'N' AND drname LIKE 'sish%'
GROUP BY
drname;
You don't need case which is expensive:
select drname,
sum(if(month(loaddate) = 1 ,drvalue,0) as 'Jan',
sum(if(month(loaddate) = 2 , drvalue ,0) as 'Feb',
sum(if(month(loaddate) = 3 , drvalue ,0) as 'March',
sum(if(month(loaddate) = 4 , drvalue ,0) as 'April',
sum(if(month(loaddate) = 5 , drvalue ,0) as 'May',
sum(if(month(loaddate) = 6 , drvalue ,0) as 'June'
from tblloadschedule
where cancelloadflag = 'N' and drname like 'sish%'
group by drname
EDIT without use of IF:
select drname,
sum((month(loaddate) = 1 ) * drvalue) as 'Jan',
sum((month(loaddate) = 2 ) * drvalue) as 'Feb',
sum((month(loaddate) = 3 ) * drvalue) as 'March',
sum((month(loaddate) = 4 ) * drvalue) as 'April',
sum((month(loaddate) = 5 ) * drvalue) as 'May',
sum((month(loaddate) = 6 ) * drvalue) as 'June'
from tblloadschedule
where cancelloadflag = 'N' and drname like 'sish%'
group by drname
The method from A. Colonna with the IF definitely worked out more efficient on the server and returned the desired results.
Many thanks to all who commented.
The code I used is:
select drname,
sum((month(loaddate) = 1 ) * drvalue) as 'Jan',
sum((month(loaddate) = 2 ) * drvalue) as 'Feb',
sum((month(loaddate) = 3 ) * drvalue) as 'March',
sum((month(loaddate) = 4 ) * drvalue) as 'April',
sum((month(loaddate) = 5 ) * drvalue) as 'May',
sum((month(loaddate) = 6 ) * drvalue) as 'June'
from tblloadschedule
where cancelloadflag = 'N'
group by drname

i cant able to sort (Ascending/Descending) this part of MySql query?

i want to sort these elements either ascending / descending.
Part of query:
sum(CASE WHEN a.question_id=39 AND u.answer_id =215 THEN 1 ELSE 0 END) as optcount1,
sum(CASE WHEN a.question_id=39 AND u.answer_id =216 THEN 1 ELSE 0 END) as optcount2,
sum(CASE WHEN a.question_id=39 AND u.answer_id =217 THEN 1 ELSE 0 END) as optcount3,
sum(CASE WHEN a.question_id=39 AND u.answer_id =218 THEN 1 ELSE 0 END) as optcount4,
Full query:
SELECT 39 AS ques_id,215 as optid1,216 as optid2,217 as optid3,218 as optid4,
'Easy to start the business' as optans1,
'Lower tax rate than a corporation' as optans2,
'Liability is shared' as optans3,
'Owner has total control and say over business' as optans4,
sum(CASE WHEN a.question_id=39 AND u.answer_id =215 THEN 1 ELSE 0 END) as optcount1,
sum(CASE WHEN a.question_id=39 AND u.answer_id =216 THEN 1 ELSE 0 END) as optcount2,
sum(CASE WHEN a.question_id=39 AND u.answer_id =217 THEN 1 ELSE 0 END) as optcount3,
sum(CASE WHEN a.question_id=39 AND u.answer_id =218 THEN 1 ELSE 0 END) as optcount4,
'217' as answer, 4 as count FROM `user_training_answers_statistics` as u,
answers as a WHERE a.question_id='39' AND u.answer_id=a.answer_id
Anyone please give me the solution for this..
Wrap it in another query then do the sorting:
select * from
(SELECT 39 AS ques_id,215 as optid1,216 as optid2,217 as optid3,
218 as optid4, 'Easy to start the business' as optans1,
'Lower tax rate than a corporation' as optans2,
'Liability is shared' as optans3,
'Owner has total control and say over business' as optans4,
sum(CASE WHEN a.question_id=39 AND u.answer_id =215 THEN 1 ELSE 0 END)
as optcount1,
sum(CASE WHEN a.question_id=39 AND u.answer_id =216 THEN 1 ELSE 0 END)
as optcount2,
sum(CASE WHEN a.question_id=39 AND u.answer_id =217 THEN 1 ELSE 0 END)
as optcount3,
sum(CASE WHEN a.question_id=39 AND u.answer_id =218 THEN 1 ELSE 0 END)
as optcount4, '217' as answer, 4 as count
FROM user_training_answers_statistics as u,
answers as a
WHERE a.question_id='39' AND u.answer_id=a.answer_id) as tmpTable
ORDER BY optcount1, optcount2, optcount3, optcount4 ASC;

PIVOT ouput in stored procedure in sql server 2008 [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
dynamic sql pivot in sql server
How to alter this stored procedure for PIVOT output
SELECT COUNT(Rly) AS TheCount, Rly FROM SPAD
WHERE Rly IN ('CR', 'ER', 'ECR', 'ECoR', 'NR', 'NCR', 'SR', 'SCR', 'SER', 'SECR', 'WR', 'WCR', 'Kolkata')
GROUP BY Rly
This ASSUMES that you have a finite number of rlys values; The only other current way to achieve this is to use DYNAMIC SQL if there are more values. (Searching for link)
Select
sum(case when rly = 'CR' then 1 else 0 end) as "CR",
sum(case when rly = 'ER' then 1 else 0 end) as "ER",
sum(case when rly = 'ECR' then 1 else 0 end) as "ECR",
sum(case when rly = 'ECoR' then 1 else 0 end) as "ECoR",
sum(case when rly = 'NR' then 1 else 0 end) as "NR",
sum(case when rly = 'NCR' then 1 else 0 end) as "NCR",
sum(case when rly = 'SR' then 1 else 0 end) as "SR",
sum(case when rly = 'SCR' then 1 else 0 end) as "SCR",
sum(case when rly = 'SER' then 1 else 0 end) as "SER",
sum(case when rly = 'SECR' then 1 else 0 end) as "SECR",
sum(case when rly = 'WR' then 1 else 0 end) as "WR",
sum(case when rly = 'WCR' then 1 else 0 end) as "WCR",
sum(case when rly = 'Kolkata' then 1 else 0 end) as "Kolkata"
FROM SPAD
EDITED After acceptance to change from count to sum.