mysql self join - mysql

I have a table called receiving with 4 columns:
id, date, volume, volume_units
The volume units are always stored as a value of either "Lbs" or "Gals".
I am trying to write an SQL query to get the sum of the volumes in Lbs and Gals for a specific date range. Something along the lines of: (which doesn't work)
SELECT sum(p1.volume) as lbs,
p1.volume_units,
sum(p2.volume) as gals,
p2.volume_units
FROM receiving as p1, receiving as p2
where p1.volume_units = 'Lbs'
and p2.volume_units = 'Gals'
and p1.date between "2012-01-01" and "2012-03-07"
and p2.date between "2012-01-01" and "2012-03-07"
When I run these queries separately the results are way off. I know the join is wrong here, but I don't know what I am doing wrong to fix it.

SELECT SUM(volume) AS total_sum,
volume_units
FROM receiving
WHERE `date` BETWEEN '2012-01-01'
AND '2012-03-07'
GROUP BY volume_units

You can achieve this in one query by using IF(condition,then,else) within the SUM:
SELECT SUM(IF(volume_units="Lbs",volume,0)) as lbs,
SUM(IF(volume_units="Gals",volume,0)) as gals,
FROM receiving
WHERE `date` between "2012-01-01" and "2012-03-07"
This only adds volume if it is of the right unit.

This query will display the totals for each ID.
SELECT s.`id`,
CONCAT(s.TotalLbsVolume, ' ', 'lbs') as TotalLBS,
CONCAT(s.TotalGalVolume, ' ', 'gals') as TotalGAL
FROM
(
SELECT `id`, SUM(`volume`) as TotalLbsVolume
FROM Receiving a INNER JOIN
(
SELECT `id`, SUM(`volume`) as TotalGalVolume
FROM Receiving
WHERE (volume_units = 'Gals') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) b ON a.`id` = b.`id`
WHERE (volume_units = 'Lbs') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) s

this is a cross join with no visible condition on the join, i don't think you meant that
if you want to sum quantities you don't need to join at all, just group as zerkms did

You can simply group by date and volume_units without self-join.
SELECT date, volume_units, sum(volume) sum_vol
FROM receving
WHERE date between "2012-01-01" and "2012-03-07"
GROUP BY date, volume_units
Sample test:
select d, vol_units, sum(vol) sum_vol
from
(
select 1 id, '2012-03-07' d, 1 vol, 'lbs' vol_units
union
select 2 id, '2012-03-07' d, 2 vol, 'Gals' vol_units
union
select 3 id, '2012-03-08' d, 1 vol, 'lbs' vol_units
union
select 4 id, '2012-03-08' d, 2 vol, 'Gals' vol_units
union
select 5 id, '2012-03-07' d, 10 vol, 'lbs' vol_units
) t
group by d, vol_units

Related

Compute 2 subqueries then group by date

I have this Table
I want to run subqueries first then add them together grouped by date
Expected Result should be like this:
I am running this query
(
SELECT DATE_FORMAT(dd1.modified_datetime,'%Y-%m-%d') as date, (v1+v2) as value FROM
(SELECT modified_datetime, Sum(data->"$.amount") as v1
FROM transactions
GROUP BY modified_datetime) as dd1 ,
(SELECT modified_datetime, MAX(data->"$.amount") as v2
FROM transactions
GROUP BY modified_datetime) as dd2
GROUP BY dd1.modified_datetime, value
)
and getting this result:
Use JOIN between subqueries and every next one:
(SELECT modified_datetime, Sum(data->"$.amount") as v1
FROM transactions
GROUP BY modified_datetime) as dd1 JOIN
(SELECT modified_datetime, MAX(data->"$.amount") as v2
FROM transactions
GROUP BY modified_datetime) as dd2 ON dd1.modified_datetime=dd2.modified_datetime
If I followed you correctly, you can use union all and aggregation:
select date_format(dt, '%Y-%m-%d') dt_day, sum(amount) value
from (
select modified_datetime dt, data ->> '$.amount' amount from transactions
union all
select created_datetime, data ->> '$.amount' from transactions
) t
group by dt_day
order by dt_day

Single Query to Count Data from Multiple Table Mysql

I have tables that contain same field, for example:
p_central_ticket p_south_ticket p_west_ticket
=====================================================================
- t_id - t_id - t_id
- t_req_type - t_req_type - t_req_type
- t_status - t_status - t_status
And i have one table :
m_event_type
=============
- ev_type
- ev_activity
My current query :
SELECT ev_activity AS Activity, COUNT( * ) AS Total
FROM m_event_type
LEFT JOIN p_central_ticket ON p_central_ticket.t_req_type = m_event_type.ev_type
WHERE t_status =9
GROUP BY ev_activity
Output from query above:
My question is, how should i do, if i want to total count from 3 tables above.
(For Example Activity Change Request total 18000, count from
p_central_ticket + p_south_ticket + p_west_ticket) etc.
Thanks...
Use union all in a subquery, then join it:
select t1.ev_Activity, count(t1.*) as total
from m_event_type t1
LEFT JOIN
(
select *
from p_central_ticket
WHERE t_status =9
union all
select *
from p_south_ticket
WHERE t_status =9
union all
select *
from p_west_ticket
WHERE t_status =9
) t2
ON t2.t_req_type = t1.ev_type
GROUP BY t1.ev_activity
Use a UNION ALL (to avoid removing duplicates) then SUM the quantities
Note that it also works if your tables have different column names you only need to alias them in the select.
SELECT ev_activity AS Activity, SUM(quantity) AS Total
FROM m_event_type met
LEFT JOIN (SELECT c.t_req_type, COUNT(*) as quantity
FROM p_central_ticket c
WHERE c.t_status =9
GROUP BY c.t_req_type
UNION ALL
SELECT s.t_req_type, COUNT(*)
FROM p_south_ticket s
WHERE s.t_status =9
GROUP BY s.t_req_type
UNION ALL
SELECT w.t_req_type, COUNT(*)
FROM p_west_ticket w
WHERE w.t_status =9
GROUP BY w.t_req_type) p ON
p.t_req_type = met.ev_type
GROUP BY ev_activity
You could use UNION ALL for select all the rows of the 3 tables
SELECT ev_activity AS Activity, COUNT( * ) AS Total
FROM m_event_type
LEFT JOIN (
select t_id, t_req_type, t_status
from p_central_ticket
union all
select t_id, t_req_type, t_status
from p_south_ticket
union all
select t_id, t_req_type, t_status
from p_west_ticket
) t ON t.t_req_type = m_event_type.ev_type
WHERE t.t_status =9
GROUP BY ev_activity

mySQL - show first and last log from each day

i have a mysql table with colums: id(primary), name(varchar), TIME(timestamp)
ID , NAME , TIME
i want to get just first and last log for each day
example if i have data like this
1,name,2018-20-21 12:35:00
2,name,2018-20-21 13:38:00
3,name,2018-20-21 14:25:00
4,name,2018-20-21 15:39:00
5,name,2018-20-21 21:48:00
6,name,2018-20-22 13:25:00
7,name,2018-20-22 14:39:00
8,name,2018-20-22 19:48:00
i want to get in just this
1,name,2018-20-21 12:35:00
5,name,2018-20-21 21:48:00
6,name,2018-20-22 13:25:00
8,name,2018-20-22 19:48:00
Try this:
SELECT name, MAX(time), MIN(time) FROM Table GROUP BY DATE(time);
You could use the union for the min and the max time group by date
and join this with your table
select * from my_table
inner join (
select * from (
select min(time) my_time
from my_table
group by date(time)
union
select max(time)
from my_table
group by date(time)
) t on t.my_time = my_table.time
order by my_table.time
Hope this helps.
SELECT id, tmp.name, tmp.time FROM
(SELECT id, name, min(time) as time FROM table1 GROUP BY DATE(time)
UNION ALL
(SELECT id, name, max(time) as time FROM table1 GROUP BY DATE(time)) tmp
ORDER BY tmp.time
You can try selecting the min and max for each day, since you want the entire line, a join is needed
and to filter out the actual min and max day, a aub query is needed
SELECT id, name, time
FROM
(
SELECT t2.*, MIN(DATE(t.time)) As min0 MAX(DATE(t.time)) As max0
FROM
table t
INNER JOIN table t2 ON t.id = t2.id
GROUP BY
DATE (t.time),
min0,
max0
) a
SELECT
l.id,l.name,l.time
FROM
log l
LEFT JOIN
(SELECT
max(time) as maxTime
FROM
log
GROUP BY date(time)) l1 ON l.time = l1.maxTime
LEFT JOIN
(SELECT
min(time) as minTime
FROM
log
GROUP BY date(time)) l2 ON l.time = l2.minTime
WHERE
(maxTime IS NOT NULL
OR minTime IS NOT NUll);
SELECT * from stack.log;

MYSQL GROUP BY multiple derived tables?

I have this query which does some calculations based on some derived tables that are linked with an INNER JOIN.
At the moment I have a WHERE clause which pulls out one id at a time. But how can I make it list all the ids?
I have tried GROUP BY in various places but can't figure it out.
My query so far is as follows:
SELECT
equipment_id,
service_duration,
available_duration,
(available_duration / service_duration)*100 AS availability
FROM (
SELECT
SUM(service_end_time - service_start_time) AS service_duration
FROM(
SELECT equipment_id,
(CASE
END) AS service_start_time,
(CASE
END) AS service_end_time
FROM t1
WHERE equipment_id = 'EX123'
)AS A
) AS B
JOIN(
SELECT equipment_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM (
SELECT equipment_id,
(CASE
END) AS available_start_time,
(CASE
END) AS available_end_time
FROM t2
WHERE equipment_id = 'EX123'
) AS C
) AS D
ON equipment_id=D.equipment_id
What I want to do is replace the WHERE clause with a GROUP BY to list all the ids, or similar, but getting that to work is beyond my skill level... Any help greatly appreciated :)
Try below:
SELECT
equipment_id, service_duration, available_duration,
(available_duration / service_duration)*100 AS availability
FROM
(
SELECT equipment_id,
SUM(service_end_time - service_start_time) AS service_duration
FROM
(
SELECT equipment_id,
(CASE ... END) AS service_start_time,
(CASE ... END) AS service_end_time
FROM t1
) AS A
GROUP BY equipment_id
) AS B
JOIN
(
SELECT equipment_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM
(
SELECT equipment_id,
(CASE ... END) AS available_start_time,
(CASE ... END) AS available_end_time
FROM t2
) AS C
GROUP BY equipment_id
) AS D
ON equipment_id=D.equipment_id
Try this (replace my field names with your field names):
SELECT
a.emp_id,
service_duration,
available_duration
FROM
(
SELECT
emp_id,
SUM(service_end_time - service_start_time) AS service_duration
FROM
data
GROUP BY
emp_id
) a
JOIN
(
SELECT
emp_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM
data
GROUP BY
emp_id
) b
ON a.emp_id = b.emp_id
GROUP BY
a.emp_id

MySQL SELECT Query - Subtract a SUM() value with the combined total of two other SUM() values

I have two SELECT statements that give the values "TotalSales" and "VendorPay_Com". I want to be able to subtract VendorPay_Com from TotalSales within the one MySQL statement to get the value "Outstanding_Funds" but I haven't found a reliable way to do so.
These are my two statements:
Query 1:
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold';
Query 2:
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
Any help on this matter would be greatly appreciated :)
You can do it as follows :
select (select ...) - (select ...)
In your example, simply :
select
(
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold'
)
-
(
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
) AS Outstanding_Funds
Try
SELECT TotalSales-VendorPay_Comm AS Outstanding_Funds
FROM
(SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold') t1,
(SELECT SUM(Amount) AS VendorPay_Comm
FROM (SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS Amount
FROM COMMISSION
WHERE Status = 'Paid') t0) t2
Here is sqlfiddle