MySQL: SUM of a column based on a value of another column - mysql

I want to have a sum of a column that is based if the value of another column is this/that. Here's my table structure
id leave_hours leave_type overtime_hours employee_id
1 7.6 1 0 3
2 5 2 0 3
3 0 0 2.3 3
I have this query already but I need to have a column that will only sum if leave type is 1 and if the leave type is 2
SELECT employee_id, SUM(overtime_hours) AS ot_hrs, SUM(leave_hours if leave_type == 1) AS
leave_1, SUM(leave_hours if leave_type == 2) AS leave_2
FROM table
GROUP BY employee_id
Result should be:
employee_id ot_hrs leave_1 leave_2
3 2.3 7.6 5
Thanks for your inputs.

You need to use conditional aggregation to sum the different leave_hours separately:
SELECT employee_id,
SUM(overtime_hours) AS ot,
SUM(CASE WHEN leave_type = 1 THEN leave_hours ELSE 0 END) AS leave_1,
SUM(CASE WHEN leave_type = 2 THEN leave_hours ELSE 0 END) AS leave_2
FROM `table`
GROUP BY employee_id
Output:
employee_id ot leave_1 leave_2
3 2.3 7.6 5
Demo on dbfiddle
Note that if you use floating point numbers to store the hours, you may need to ROUND the results.

you can use max() with case when
SELECT employee_id,
max(overtime_hours) AS ot,
max(CASE WHEN leave_type = 1 THEN leave_hours END) AS leave_1,
max(CASE WHEN leave_type = 2 THEN leave_hours END) AS leave_2
FROM table_name
GROUP BY employee_id
output
employee_id ot leave_1 leave_2
3 2.3 7.599999904632568 5

Related

Set SQL ordering by highest earnings/losses

I would like to use two kinds of ordering.
From the highest earnings
From the highest losses.
My database looks like this
id
saldo
saldo_type
7
75,67
1
10
7
1
3
5,45
1
11
12,3
0
4
6,45
0
saldo_type:
1 = earnings
0 = losses
Expected result/output for sort by highest earnings:
id
saldo
saldo_type
7
75,67
1
10
7
1
3
5,45
1
4
6,45
0
11
12,3
0
and by highest losses:
id
saldo
saldo_type
11
12,3
0
4
6,45
0
3
5,45
1
10
7
1
7
75,67
1
So far I am stuck with such a code
SELECT id, saldo, saldo_type FROM `investitions`
ORDER BY
(CASE WHEN saldo_type = "1" THEN saldo END) DESC,
(CASE WHEN saldo_type = "0" THEN saldo END) ASC
Expected result/output:
sort by highest earnings
sort by highest losses
One way would be to convert the losses to negative values then you will achieve your goal. In your case, try the following:
SELECT id, saldo, saldo_type FROM `investitions`
ORDER BY (CASE WHEN saldo_type = "1" THEN saldo else -saldo END) desc
Cast saldo to decimal
SELECT id, saldo, saldo_type FROM `investitions`
ORDER BY saldo_type desc,cast(replace(saldo,',','.') as decimal(4,2)) desc -- sort by highest earnings
Adjust the precision and scale according to your data.
Thank you very much. I was able to build a working query using a piece of each answer.
Query looks like this:
SELECT id, saldo, saldo_type FROM `investitions` ORDER BY (CASE WHEN saldo_type = "1" THEN cast(replace(saldo,',','.') as decimal(12,2)) else -cast(replace(saldo,',','.') as decimal(12,2)) END) desc

How to achieve MySQL Query combining multiple COUNT() and GROUP BY

I have this data:
id date userid result
1 2015-05-01 1 a
2 2015-05-02 1 b
3 2015-05-03 1 b
4 2015-05-03 1 a
5 2015-05-04 1 a
I need to get users sorted by result:
id a b
1 1 1
2 1 1
You want conditional aggregation:
SELECT user_id, sum(result = 'win') AS wins, sum(result = 'loss') as losses
FROM table
GROUP BY user_id
ORDER BY wins DESC
LIMIT 4;
I would do it like this:
SELECT user_id,
SUM(CASE WHEN result='win' THEN 1 ELSE 0 END) AS wins,
SUM(CASE WHEN result='loss' THEN 1 ELSE 0 END) AS losses
FROM table1
GROUP BY user_id
ORDER BY wins DESC
LIMIT 4
Fiddle is here: http://sqlfiddle.com/#!9/00ac7/8

MySQL select using row counts and grouping

I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped

Looking for Mysql query

I have mysql table with following 3 fields:
- vouchercode: Unique KEY
- voucherstatus: 1 for unused voucher, 3 for used voucher
- partnerId
I want to display how many vouchers are used and unused w.r.t partnerId.
Example :- table data
PartnerId voucherstaus vouchercode(unique)
1 1
1 3
1 1
2 3
2 3
2 1
Result:
PartnerId usedvouchers unusedvouchers
1 1 2
2 2 1
Please help me with mysql query for same. Seems i have to use subquery and group by doesn't work. Thanks in advance
SELECT partnerID,
SUM(CASE WHEN voucherstatus = 1 THEN 1 ELSE 0 END) unusedvouchers,
SUM(CASE WHEN voucherstatus = 3 THEN 1 ELSE 0 END) usedvouchers
FROM data
GROUP BY partnerID
SQLFiddle Demo
SQLFiddle Demo (will work only in MySQL)
select PartnerId, SUM(case when voucher_status =1 then 1 else 0 end) as unused, sum(case when voucher_status =3 then 1 else 0 end) as used from Voucher group by PartnerID;
sqlfiddle *demo*

MySQL query to count non-null values in a single row

I'm trying to put together a MYSQL query that will count the number of Non-Null (or better yet, non-zero) values in select fields in a single row and then sort from lowest to highest (based on the count). For example, I have a table with 5 fields... ID, Name, Score_1, Score_2, Score_3. I want to count how many times the value "0" exists in Score_1, Score_2 and Score_3 for each record, then sort from most non zero values to least.
ID Name Score_1 Score_2 Score_3
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
4 Mike 4 5 5
I assume the query has to look something like this...
Select ID, Name, Score_1, Score_2, Score_3 where (???) ORDER BY (???)
Output should look like this (ID 4 is displayed first since it has the least amount of non-zero entries)...
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
I'm somewhat new to mysql query's, so any help would be greatly appreciated. I thought the COUNT function would help, but that function appears to count columns from all rows. Perhaps there is a way to use the COUNT function and limit it to a singel row so it can be sorted by that row count?
This should do what you want:
SELECT ID, Name, Score_1, Score_2, Score_3
FROM Table1
ORDER BY (Score_1 = 0) + (Score_2 = 0) + (Score_3 = 0)
Result:
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
try This:
Select id, Count1, Count2, Count3, Count4
From
(Select
Sum(Case When IsNull(Score_1,0) = 0 Then 1 Else 0 End) Count1,
Sum(Case When IsNull(Score_2,0) = 0 Then 1 Else 0 End) Count2,
Sum(Case When IsNull(Score_3,0) = 0 Then 1 Else 0 End) Count3,
Sum(Case When IsNull(Score_4,0) = 0 Then 1 Else 0 End) Count4
From Table
Group By Id) Z -- This column (Id) better not be the PK for this table!!!
Order By Count1 + Count2 + Count3 + Count4