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
Related
This is my query
SELECT `email`, `score`, `score` * 100 / t.s AS `Grade Percentage %`
FROM `rank`
CROSS JOIN (SELECT SUM(`level`) AS s FROM `history`) t
GROUP BY `email`
rank Table:
history Table:
my desired output for example with kemp score after multiplying the score of kemp by 100, i want to divide it with the total of his level which is 4. help me i cant seem to solve the problem
You could also use only subquery instead
SELECT r.email, r.score,
(r.score * 100 / (SELECT SUM(level)
FROM history
WHERE email = r.email)) AS `Grade Percentage %`
FROM rank r;
However, this assumes always rank table has only one copy of email, else you would need to use GROUP BY
Edit :
update rank r
set r.`Grade Percentage %` = (r.score * 100 / (SELECT SUM(level)
FROM history
WHERE email = r.email));
Use sub query with GROUP BY in the join as below
SELECT r.email,
r.score,
(r.score * 100 / t.lvl) AS `Grade Percentage %`
FROM `rank` r
INNER JOIN (SELECT
email, SUM(`level`) lvl
FROM `history` GROUP BY email) t ON t.email = r.email
To store result in the column Grade Percentage % of rank table
UPDATE `rank` r
INNER JOIN (SELECT
email, SUM(`level`) lvl
FROM `history` GROUP BY email) t ON t.email = r.email
SET `Grade Percentage %` = (r.score * 100 / t.lvl)
I'm trying to create a query to update the rank field of all the records in the table, based on values from the same table.
I managed to get a working SELECT query that calculates the rank, but I'm having a hard time converting it to an UPDATE. This is the query:
SELECT
((views_count + comments_count) * (172800 / elapsed)) AS rank
FROM (
SELECT
p.views_count,
(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(p.createdAt)) AS elapsed,
(SELECT COUNT(*) FROM `comments` AS c WHERE c.photo_id = p.id) AS comments_count
FROM `photos` AS p
) AS m
How can I implant it in an UPDATE query, to update each record's rank value?
Thanks! :)
EDIT:
My DB structure:
[Photo]
id
user_id
views_count
rank
createdAt
[Comment]
id
photo_id
content
Just a guess, but something like this should work:
UPDATE `photos`
FROM (
SELECT id
, (views_count + comments_count) * (172800 / elapsed) AS rank
FROM (
SELECT p.id
, p.views_count
, ( UNIX_TIMESTAMP(NOW())
- UNIX_TIMESTAMP(p.createdAt)) AS elapsed
, (SELECT COUNT(*)
FROM `comments` AS c
WHERE c.photo_id = p.id) AS comments_count
FROM `photos` AS p
) AS m
) AS z
SET rank=z.rank
WHERE `photos`.id=z.id
You should write your new ranks to a temporary table and use that to update the original table. try
CREATE TEMPORARY TABLE tmp_tbl AS (
SELECT ((views_count + comments_count) * (172800 / elapsed)) AS rank, m.id
FROM (SELECT
p.views_count,
(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(p.createdAt)) AS elapsed,
(SELECT COUNT(*) FROM `comments` AS c WHERE c.photo_id = p.id) AS comments_count
FROM `photos` AS p
) AS m);
and then
UPDATE photos, tmp_tbl SET photos.rank = tmp_tbl.rank WHERE photos.id=tmp_tbl.id;
and finally
DROP TABLE tmp_tbl;
See this simliar stackoverflow question
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 ...
...
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
I should note that id is not unique in the tdemog_pfp table - there is a unique field there that auto-increments - could this be an issue?
Ok, I have the following SQL query:
SELECT id, name, total_staff AS StaffCount, COUNT( q60a ) AS TotalResp, (COUNT( q60a ) / total_staff * 100) AS Perc
FROM tdemog_pfp
LEFT JOIN tresults_pfp ON tdemog_pfp.id = tresults_pfp.q60a
GROUP BY name
ORDER BY name
Now, the demog table has multiple rows where entries can have q59, q60a, q60b and so on for the colomn qnum
I want to bring back the results WHERE qnum = q60a but I have a problem, when I add it to the above to make the following - it brings back zero results (an empty result set), which is incorrect:
SELECT id, name, total_staff AS StaffCount, COUNT( q60a ) AS TotalResp, (COUNT( q60a ) / total_staff * 100) AS Perc
FROM tdemog_pfp
LEFT JOIN tresults_pfp ON tdemog_pfp.id = tresults_pfp.q60a
WHERE qnum = q60a
GROUP BY name
ORDER BY name
Where am I going wrong?
Thanks,
H.
Make your test part of the JOIN condition instead of testing in the WHERE clause.
SELECT id, name, total_staff AS StaffCount, COUNT( q60a ) AS TotalResp, (COUNT( q60a ) / total_staff * 100) AS Perc
FROM tdemog_pfp
LEFT JOIN tresults_pfp ON tdemog_pfp.id = tresults_pfp.q60a
AND qnum = q60a
GROUP BY name
ORDER BY name
Doing this: WHERE qnum = q60a is transforming your query into an inner join; hence, no results in this case.