Calculate difference of columns of two tables - mysql

I am a newbie in mysql and php and not so experienced yet in making complicated queries.
Thanks of some users on stackoverflow below query is now successfully working.
the last bit I am missing now is to include calculating the difference between total from q1 and costs from q2 in this query. Thanks for your help in advance. cheers
Select * from ( SELECT invoice.eventid, invoice.invoiceno, event.clientid, client.clientid, clientname,
gross_amount, vat, total, due
FROM client, invoice, event
WHERE event.eventid = invoice.eventid
AND event.clientid = client.clientid)
as q1
inner JOIN (SELECT event_ma.eventid,
salary.staffid, Sum(cost_hour * Time_to_sec(Timediff(hours, pause))) / 3600 AS costs
FROM salary
JOIN event_ma ON salary.staffid = event_ma.staffid GROUP BY event_ma.eventid)
as q2
ON q1.eventid = q2.eventid
GROUP BY q1.eventid

Add the calculated field in your primary SELECT-statement:
Select *, (q1.total - q2.costs) AS difference
from ( SELECT invoice.eventid, invoice.invoiceno, event.clientid, client.clientid, clientname,
gross_amount, vat, total, due
FROM client, invoice, event
WHERE event.eventid = invoice.eventid
AND event.clientid = client.clientid)
as q1
inner JOIN (SELECT event_ma.eventid,
salary.staffid, Sum(cost_hour * Time_to_sec(Timediff(hours, pause))) / 3600 AS costs
FROM salary
JOIN event_ma ON salary.staffid = event_ma.staffid GROUP BY event_ma.eventid)
as q2
ON q1.eventid = q2.eventid
GROUP BY q1.eventid

Related

MySQL Query to calculate unique id, count number of records and group by (3 tables)

I have 3 tables engagements, patient_services and patients.
This Query
SELECT
ps_user_loc AS loc, COUNT(ps_id) AS ser, Count(Distinct ps_ur) AS patient
FROM patient_services
GROUP BY loc
UNION ALL
SELECT
eng_user_loc AS loc, COUNT(eng_id) AS ser, Count(Distinct eng_ur) AS patient
FROM engagements
WHERE LENGTH( eng_ur )>0
GROUP BY loc
returns
loc ser patient
CABOOLTURE 354 255
KILCOY 15 12
RBWH 1840 476
RBWH 34 27
REDCLIFFE 3 3
TPCH 11 9
So loc has doubles and I can calculate ser in php loop
But Patients count not unique because the same id in engagements and patient_services tables.
How to make select grouped by Location with number of Services and unique Patients in two tables(not in each like it now)?
Thank you.
What you are looking for is a full outer join. That would be two steps: 1. get loc/patient pairs from the tables and join, 2. aggregate by loc. In standard SQL:
select
loc,
sum(coalesce(ps.cnt, 0) + coalesce(e.cnt, 0)),
count(distinct patient)
from
(
select
ps_user_loc as loc,
ps_ur as patient,
count(*) as cnt
from patient_services
group by ps_user_loc, ps_ur
) ps
full outer join
(
select
eng_user_loc as loc,
eng_ur as patient
count(*) as cnt,
from engagements
where length(eng_ur) > 0
group by eng_user_loc, eng_ur
) e using (loc, patient)
group by loc;
Unfortunately MySQL doesn't support full outer joins (and the using clause neither). One way is to get all locs/patients first and then left join:
select
l.loc,
sum(coalesce(ps.cnt, 0) + coalesce(e.cnt, 0)),
count(distinct l.patient)
from
(
select ps_user_loc as loc, ps_ur as patient from patient_services
union
select eng_user_loc as loc, eng_ur as patient from engagements
) l
left outer join
(
select
ps_user_loc as loc,
ps_ur as patient,
count(*) as cnt
from patient_services
group by ps_user_loc, ps_ur
) ps on ps.loc = l.loc and ps.patient = l.patient
left outer join
(
select
eng_user_loc as loc,
eng_ur as patient,
count(*) as cnt
from engagements
where length(eng_ur) > 0
group by eng_user_loc, eng_ur
) e on e.loc = l.loc and e.patient = l.patient
group by l.loc;

Joining two select queries

I want to join two select queries and don't know how to do it.
The first query gives me information on the invoice number, the client, the eventid and the amount that are all saved in the invoice table :
SELECT invoice.Eventid, invoice.Invoiceno,
event.clientid, client.clientid, clientname, gross_amount, VAT, total, due
FROM client, invoice, event,
WHERE event.eventid=invoice.eventid and event.clientid = client.clientid group by invoice.eventid
The second query is checking the salary of the staffmember
SELECT event_ma.eventid, salary.staffid, SUM( cost_hour * TIME_TO_SEC( TIMEDIFF( hours, pause ) ) ) /3600 AS costs
FROM salary
JOIN event_ma ON salary.staffid = event_ma.staffid
GROUP BY event_ma.eventid
At the end I want to see the all relevant costs and income per event.
The way I understand the question, you can take the first query, and then join the second query where the eventID matches. Also, just pointing out that you're using old join syntax in the first query - rather than using:
Select table1.col, table2.col From
table1, table2
...
You should use:
Select table1.col, table2.col From
table1
INNER JOIN table2 On
table1.colID = table2.colID
...
And to answer your question:
SELECT invoice.eventid,
invoice.invoiceno,
event.clientid,
client.clientid,
clientname,
gross_amount,
vat,
total,
due
FROM client,
invoice,
event,
inner
JOIN (SELECT event_ma.eventid,
salary.staffid,
Sum(cost_hour * Time_to_sec(Timediff(hours, pause))) / 3600
AS
costs
FROM salary
JOIN event_ma
ON salary.staffid = event_ma.staffid
GROUP BY event_ma.eventid) x
ON invoice.eventid = x.eventid
WHERE event.eventid = invoice.eventid
AND event.clientid = client.clientid
GROUP BY invoice.eventid
You can actually use this way:
CREATE VIEW `inv` AS
SELECT invoice.Eventid AS inve, invoice.Invoiceno,
event.clientid, client.clientid, clientname, gross_amount, VAT, total, due
FROM client, invoice, event,
WHERE event.eventid=invoice.eventid and event.clientid = client.clientid group by invoice.eventid
CREATE VIEW `ev` AS
SELECT event_ma.eventid AS evee, salary.staffid, SUM( cost_hour * TIME_TO_SEC( TIMEDIFF( hours, pause ) ) ) /3600 AS costs
FROM salary
JOIN event_ma ON salary.staffid = event_ma.staffid
GROUP BY event_ma.eventid
And your final query as:
SELECT * FROM `inv`, `ev`
WHERE `inve` = `evee`;
Or you can also consider using MySQL JOIN this way:
SELECT * FROM `inv`
JOIN `ev` ON `inv`.`inve` = `ev`.`evee`;
You can write a query that takes subqueries as data sources:
select ...
from
(select ...) as q1
inner join (select ...) as q2 on ...
...

Is it possible to simplify this SQL statement with multiple subqueries and JOINs

I've spent a couple of days creating this rather complicated SQL statement, and it now gives me exactly what I want. Now I'm wondering if there is a better/simpler way to do it. Also MySQL wont let me CREATE VIEW on this statement
SELECT name, a.user, liste, c.order, total_1kr, total_5kr, total_8kr, total_10kr, total_paid, differens, sbdato, spaid, sbreg, sfdato, sforbrug, sfreg
FROM (SELECT t.user, t.paid AS spaid, t.dato AS sbdato, t.registrant AS sbreg FROM(
SELECT user,MAX(dato) AS maksdato
FROM g_kiosk_f WHERE paid!=0
GROUP BY user) AS x
JOIN g_kiosk_f AS t ON x.user =t.user
AND x.maksdato = t.dato) AS a
JOIN (SELECT s.user, (s.1kr+(s.5kr)*5+(s.8kr)*8+(s.10kr)*10) AS sforbrug, s.dato AS sfdato, s.registrant AS sfreg FROM(
SELECT user,MAX(dato) AS maksdato
FROM g_kiosk_f WHERE 1kr!=0 OR 5kr!=0 OR 8kr!=0 OR 10kr!=0
GROUP BY user) AS y
JOIN g_kiosk_f AS s ON y.user=s.user
AND y.maksdato=s.dato) AS b
JOIN (SELECT t1.name, t2.user, t1.liste, t1.order, sum( t2.1kr ) AS total_1kr, sum( t2.5kr ) *5 AS total_5kr, sum( t2.8kr ) *8 AS total_8kr, sum( t2.10kr ) *10 AS total_10kr, sum( t2.paid ) AS total_paid, ( sum( t2.1kr ) + sum( t2.5kr ) *5 + sum( t2.8kr ) *8 + sum( t2.10kr ) *10 - sum( t2.paid )) AS differens
FROM g_kiosk_users AS t1
INNER JOIN g_kiosk_f AS t2 ON t1.nr = t2.user
GROUP BY t2.user
ORDER BY t1.name ASC) AS c
ON a.user=b.user AND a.user=c.user
I have a table 'g_kiosk_f' containing id (user), date (dato), 5 kinds of transactions (1kr, 5kr, 8kr, 10kr, and paid) a cashier (registrant). Another table, 'g_kiosk_users', contains name and id (nr).
I want a result set showing
the date, registrant and amount of newest transaction where paid!=0
the date, registrant and amount of newest transaction where 1kr!=0, 5kr!=0, 8kr!=0 or 10kr!=0
the total difference of sum(1kr+5kr+8kr+10kr) and sum(paid)
So the result should look something like
Name | id | difference | newest paid date | newest paid registrant | newest paid amount | newest kr date | newest kr registrant | newest kr amount |
In the above I've included the numbers needed to do the difference calculation by hand, because it was needed at some point, but is now obsolete. Does any of this even make sense?
It seems like it should be possible to rewrite you query like this:
SELECT t1.name AS name, a.user AS user, t1.liste, t1.order,
SUM(t2.1kr) AS total_1kr, SUM(t2.5kr) * 5 AS total_5kr,
SUM(t2.8kr) AS total_8kr, SUM(t2.10kr) * 5 AS total_10kr,
SUM(52.paid) AS total_paid,
SUM(t2.1kr + 5 * tt.5kr + 8 * t2.8kr + 10 * t2.10kr)
-SUM(t2.paid) AS differens
a.dato AS sbdato, a.paid AS spaid, a.registrant as sbreg,
b.dato as sfdato,
(b.1kr+(b.5kr)*5+(b.8kr)*8+(b.10kr)*10) AS sforbrug,
b.registrant AS sfreg
FROM g_kiosk_f AS a
INNER JOIN (SELECT user, MAX(dato) FROM g_kiosk_f
WHERE paid != 0
GROUP BY user) AS a2
ON a.user = a2.user AND a.dato = a2.dato
INNER JOIN g_kiosk_f as b ON b.user = a.user
INNER JOIN (SELECT user, MAX(dato) FROM g_kiosk_f
WHERE 1kr!=0 OR 5kr!=0 OR 8kr!=0 OR 10kr!=0
GROUP BY user) AS b2
ON b.user = b2.user AND b.dato = b2.dato
INNER JOIN g_kiosk_f as t2 ON t2.user = a.user
INNER JOIN g_kiosk_users as t1 ON t1.nr = t2.user
GROUP BY a.user
ORDER BY name ASC

Help on MySQL query

I have the following table structure:
Customers - Cust_Orders - Cust_Items - Cust_Payments - Drivers
id id id id id
company cid oid oid name
driver price amount
date qty date
vat
What I want to do is showing last unpaid order marked by a specific driver id + the sum of all unpaid orders for that particular customer except the order that is already selected.
Since there might be more than one cust_items & more than one cust_payments I had to use select from select as otherwise I would have wrong sums & things got messy till I reached a point I forgot what I was doing.
Any Help would be greatly appreciated.
My current SQL which lacks the final part only (sum of other unpaid orders amounts):
SELECT `customers`.`company`,
T1.*,
ROUND( IFNULL( SUM(`cust_payments`.`amount`), 0 ), 2) AS `paid`
FROM (
SELECT `cust_orders`.*,
ROUND( IFNULL( SUM(`cust_items`.`qty` * `cust_items`.`price`), 0 ), 2) AS `total`,
SUM( ( `cust_items`.`price` * `cust_items`.`qty` * `vat` ) / 100) AS `vat`
FROM `cust_orders`
LEFT JOIN `cust_items` ON `cust_orders`.`id` = `cust_items`.`oid`
GROUP BY `cust_orders`.`id`
) `T1`
LEFT JOIN `customers` ON `T1`.`cid` = `customers`.`id`
LEFT JOIN `cust_payments` ON `T1`.`id` = `cust_payments`.`oid`
WHERE `T1`.`driver` = ? GROUP BY `T1`.`id` HAVING (`T1`.`total` - `paid`) > ?
ORDER BY `T1`.`id` DESC LIMIT 1
Can you try
SELECT
x.id,
x.company,
y.id,
y.cid,
y.driver,
y.date,
#ut:=ROUND(SUM(z.qty*z.price),2) AS unpaid_total,
#uv:=SUM((#ut*z.vat)/100) AS unpaid_vat,
#st:=ROUND(SUM(b.qty*b.price),2)-#ut AS sum_total,
SUM((#st*b.vat)/100)-#uv AS sum_vat
FROM Customers x
INNER JOIN Cust_Orders y ON x.id=y.cid
INNER JOIN Cust_Items z ON y.id=z.oid
LEFT JOIN Cust_Orders a ON x.id=a.cid
LEFT JOIN Cust_Items b ON a.id=b.oid
WHERE
y.driver=? AND
NOT EXISTS (SELECT * FROM Cust_Payments WHERE oid=y.id) AND
NOT EXISTS (SELECT * FROM Cust_Payments WHERE oid=a.id)
GROUP BY x.id,x.company, y.id, y.cid, y.driver, y.date

Mysql query - JOINS and WHERE clause, beginner here :)

having difficulties with a form and mysql. 3 tables, 1 sum of a tables values. The form provides the value to search, but it does not work with the "WHERE >= '$search_total_rating" being in the wrong place, i am doing something very wrong here.
$result = mysql_query("SELECT coffeeshops.*, services.*, ratings.*, sum(temp.total) as final_total FROM coffeeshops inner join services on coffeeshops.shop_id=services.shop_id
inner join ratings on coffeeshops.shop_id=ratings.shop_id
inner join (select SUM(comfort + service + ambience + friendliness + spacious)/(5) / COUNT(shop_id) AS total, shop_id FROM ratings GROUP BY shop_id) as temp on coffeeshops.shop_id=temp.shop_id WHERE >= '$search_total_rating'");
I do not fully understand this, but what i am trying to do is WHERE the total rating sum is >= selected rating. I am trying to access final_total which is not an actual column in my database, that is why SUM is being used to get the total rating for each shop. Hopefully it is a minor shuffle of the code. Thanks
You should use having instead of where
SELECT coffeeshops.*, services.*, ratings.*, sum(temp.total) as final_total
FROM coffeeshops inner join services on coffeeshops.shop_id=services.shop_id
inner join ratings on coffeeshops.shop_id=ratings.shop_id
inner join (
select SUM(comfort + service + ambience + friendliness + spacious)/5/ COUNT(shop_id) AS total, shop_id
FROM ratings GROUP BY shop_id)
as temp on coffeeshops.shop_id=temp.shop_id
having final_total >= '$search_total_rating'
You have already calculated your total in the subquery. No need for a second SUM().
SELECT coffeeshops.*
, services.*
, ratings.*
, temp.total as final_total
FROM coffeeshops
inner join services
on coffeeshops.shop_id = services.shop_id
inner join ratings
on coffeeshops.shop_id = ratings.shop_id
inner join
( select SUM(comfort + service + ambience + friendliness + spacious) / 5
/ COUNT(shop_id) AS total
, shop_id
FROM ratings
GROUP BY shop_id
) as temp
on coffeeshops.shop_id = temp.shop_id
WHERE temp.total >= '$search_total_rating'
You could also use a HAVING in the subquery:
SELECT coffeeshops.*
, services.*
, ratings.*
, temp.total as final_total
FROM coffeeshops
inner join services
on coffeeshops.shop_id = services.shop_id
inner join ratings
on coffeeshops.shop_id = ratings.shop_id
inner join
( select SUM(comfort + service + ambience + friendliness + spacious) / 5
/ COUNT(shop_id) AS total
, shop_id
FROM ratings
GROUP BY shop_id
HAVINGE total >= '$search_total_rating'
) as temp
on coffeeshops.shop_id = temp.shop_id