Percentage Query in MySQL - mysql

I have 2 tables as shown below :
Tabel_1
|idUnit | Budget |
|112 | 1000 |
|112 | 2000 |
|113 | 4000 |
Tabel_2
|idUnit | Real2 |
|112 | 500 |
|112 | 100 |
|113 | 200 |
My Question, how to make the table as below with percentage:
| idUnit | TotalBudget | TotalReal2 | Percentage
| 112 | 3000 | 600 | ? (15%) |
| 113 | 4000 | 200 | ? (5%) |
My query before :
SELECT t1.idUnit, SUM(Budget) AS TotalBudget, t2.TotalReal2
FROM Tabel_1 AS t1
JOIN (SELECT idUnit, SUM(Real2) AS TotalReal2
FROM Tabel_2 GROUP BY idUnit
) AS t2 ON t1.idUnit = t2.idUnit
GROUP BY t1.idUnit;

You can try to use two subqueries then do JOIN, calculating your column by TotalBudget and totalbudget
Query 1:
SELECT t1.idUnit,
t1.TotalBudget,
t2.TotalReal2,
CONCAT((TotalReal2/totalbudget)*100,'%') Percentage
FROM (
SELECT idUnit,SUM(Budget) TotalBudget
FROM Tabel_1
GROUP BY idUnit
) AS t1
INNER JOIN (
SELECT idUnit,
SUM(Real2) AS TotalReal2
FROM Tabel_2
GROUP BY idUnit
) AS t2 ON t1.idUnit = t2.idUnit
Results:
| idUnit | TotalBudget | TotalReal2 | Percentage |
|--------|-------------|------------|------------|
| 112 | 3000 | 600 | 20.0000% |
| 113 | 4000 | 200 | 5.0000% |

Related

Running query on results of a join statement

I'm trying to figure out how I can run a query on the results of a join statement I'm doing between two tables. Basically, I need to get all the entries from More_Info that match the ID of Source_Table between a certain time, and then calculate the difference between Number where PartID = certain things.
Consider the following two tables:
Source_Table
UniqueID | TimeIn |
1 | 051010|
2 | 051545|
3 | 055412|
More_Info
UniqueID | PartID | Number |
1 | 500 | 5 |
1 | 505 | 10 |
1 | 510 | 40 |
2 | 500 | 10 |
2 | 505 | 15 |
2 | 510 | 25 |
4 | 500 | 30 |
6 | 505 | 10 |
So I know I can run select * from Source_Table left join More_Info using(UniqueID) which will return:
UniqueID | PartID | Number |
1 | 500 | 5 |
1 | 505 | 10 |
1 | 510 | 40 |
2 | 500 | 10 |
2 | 505 | 15 |
2 | 510 | 25 |
From this, what I need is to get 'Number' where PartID = 500 or 505, and get the difference, where the results would be like:
UniqueID | Difference |
1 | 5 |
2 | 5 |
Having a big of difficulty wrapping my head around this, so any help would be appreciated.
You could use a couple of subquery eg:
select t1.UniqueId, t2.NUmber - t1.Number from (
select * from Source_Table left join More_Info using(UniqueID)
) t1
INNER JOIN (
select * from Source_Table left join More_Info using(UniqueID)
) t2 on t1.UniqueID = t2.UniqueID and t1.PartID = 500 and t2.partId = 505

Two querys in one [MYSQL] ONE RESULTS

can you help me guys to join two queries in one?
This is my first query:
SELECT estimated_sum_all, story_point_sum_all, time_spent, reg_date
FROM burndown_snap_all WHERE project_id='72'
Results:
| estimated_sum_all | story_point_sum_all | time_spent | reg_date |
| 300 | 20 | 20.30 | 2017-09 |
| 300 | 20 | 19.30 | 2017-09 |
| 300 | 20 | 18.30 | 2017-09 |
| 300 | 20 | 15.32 | 2017-09 |
This is my second query:
SELECT time_spent FROM status_history_hours where
project_id = '72'
Results:
| time_spent |
| 20.30 |
| 20.30 |
| 20.30 |
| 20.30 |
What I wanna to do is to build one mysql query that have to contain select/join to time_spent from the second query. Final table should looks like this:
| estimated_sum_all | story_point_sum_all | time_spent | reg_date |
| 300 | 20 | 20.30 | 2017-09 |
| 300 | 20 | 20.30 | 2017-09 |
| 300 | 20 | 20.30 | 2017-09 |
| 300 | 20 | 20.30 | 2017-09 |
Regards,
Solution for this would be like:
SELECT t1.id, t1.estimated_sum_all,
t1.story_point_sum_all, t1.time_spent,
t2.id, t2.time_spent FROM
burndown_snap_all t1, status_history_hours
t2 WHERE t1.project_id = 72 AND
t2.project_id = 72 group by t1.id
But how to group by t2.id in the same time???
SELECT estimated_sum_all, story_point_sum_all, time_spent, reg_date
FROM burndown_snap_all WHERE project_id='72'
UNION ALL
SELECT time_spent FROM status_history_hours where
project_id = '72'
From the data that you have provided, you can take any matching value from the second table. So, you could do:
SELECT bsa.estimated_sum_all, bsa.story_point_sum_all, bsa.time_spent,
bsa.reg_date,
(SELECT MAX(shh.time_spent)
FROM status_history_hours shh
WHERE shh.project_id = bsa.project_id
) as time_spent
FROM burndown_snap_all bsa
WHERE project_id = 72;

Subtract two columns of different tables with different number of rows

How can I write a single query that will give me SUM(Entrance.quantity) - SUM(Buying.quantity) group by product_id.
The problem is in rows that not exist in the first or second table. Is possible to do this?
Entrance:
+---+--------------+---------+
| id | product_id | quantity|
+---+--------------+---------+
| 1 | 234 | 15 |
| 2 | 234 | 35 |
| 3 | 237 | 12 |
| 4 | 237 | 18 |
| 5 | 101 | 10 |
| 6 | 150 | 12 |
+---+--------------+---------+
Buying:
+---+------------+-------------+
| id | product_id | quantity|
+---+------------+-------------+
| 1 | 234 | 10 |
| 2 | 234 | 20 |
| 3 | 237 | 10 |
| 4 | 237 | 10 |
| 5 | 120 | 15 |
+---+------------+------------+
Desired result:
+--------------+-----------------------+
| product_id | quantity_balance |
+--------------+-----------------------+
| 234 | 20 |
| 237 | 10 |
| 101 | 10 |
| 150 | 12 |
| 120 | -15 |
+--------------+-----------------------+
This is tricky, because products could be in one table but not the other. One method uses union all and group by:
select product_id, sum(quantity)
from ((select e.product_id, quantity
from entrance e
) union all
(select b.product_id, - b.quantity
from buying b
)
) eb
group by product_id;
SELECT product_id ,
( Tmp1.enterquantity - Tmp2.buyquantity ) AS Quantity_balance
FROM entrance e1
CROSS APPLY ( SELECT SUM(quantity) AS enterquantity
FROM Entrance e2
WHERE e1.product_id = e2.product_id
) Tmp1
CROSS APPLY ( SELECT SUM(quantity) AS buyquantity
FROM Buying b2
WHERE e1.product_id = b2.product_id
) Tmp2
GROUP BY Product_id,( Tmp1.enterquantity - Tmp2.buyquantity )

Calculate difference between one column over multiple rows using coalesce and join

I have following table
+-----+--------+-----------+-----------+-------+
| id | job_id | source_id | target_id | value |
+-----+--------+-----------+-----------+-------+
| 204 | 5283 | 247 | 228 | 1201 |
| 349 | 4006 | 247 | 228 | 100 |
| 350 | 4007 | 247 | 228 | 500 |
| 351 | 4008 | 247 | 228 | 1000 |
| 352 | 4009 | 1 | 100 | 100 |
| 353 | 4010 | 1 | 100 | 500 |
| 354 | 4011 | 1 | 100 | 50 |
+-----+--------+-----------+-----------+-------+
I want to create a diff between the column value groupped by source_id and target_id. The older one (smaller id) should be compared with the newer one
I have searched a little bit and found coalesce. I have written a small query and it works in "general", but not as expexted:
SELECT
c.id, c.source_id, c.target_id, c.value, COALESCE(c1.value - c.value, -1) AS diff
FROM
changes c LEFT JOIN changes c1 ON (c1.source_id = c.source_id AND c1.target_id = c.target_id)
GROUP BY c.source_id, c.target_id, c.job_id
ORDER BY c.id
I got following result:
+-----+-----------+-----------+-------+------+
| id | source_id | target_id | value | diff |
+-----+-----------+-----------+-------+------+
| 204 | 247 | 228 | 1201 | 0 |
| 349 | 247 | 228 | 100 | 1101 |
| 350 | 247 | 228 | 500 | 701 |
| 351 | 247 | 228 | 1000 | 201 |
| 352 | 1 | 100 | 100 | 0 |
| 353 | 1 | 100 | 500 | -400 |
| 354 | 1 | 100 | 50 | 50 |
+-----+-----------+-----------+-------+------+
You can see the diff work for id 349 and 353, I want this for all rows like the following expected result:
+-----+-----------+-----------+-------+------+
| id | source_id | target_id | value | diff |
+-----+-----------+-----------+-------+------+
| 204 | 247 | 228 | 1201 | 1201 |
| 349 | 247 | 228 | 100 | 1101 |
| 350 | 247 | 228 | 500 | -400 |
| 351 | 247 | 228 | 1000 | -500 |
| 352 | 1 | 100 | 100 | 100 |
| 353 | 1 | 100 | 500 | -400 |
| 354 | 1 | 100 | 50 | 450 |
+-----+-----------+-----------+-------+------+
It would be no problem if the diff result is inverted.
What did I miss?
Thanks for any hints.
if you use user defined variables you don't need to join the table to itself. just do a row by row comparrision like so
SELECT
id,
job_id,
target_id,
if(#a = source_id, #b - value, value) as diff,
#b := value as value,
#a := source_id as source_id
FROM changes
CROSS JOIN (SELECT #a:=0, #b:=0)t
DEMO
I suspect that you're looking for something like this - although the COALESCE bit seems misleading to me...
SELECT a.*, COALESCE(b.value-a.value,a.value) diff
FROM
( SELECT x.* , COUNT(*) rank FROM changes x JOIN changes y ON y.id <= x.id GROUP BY x.id ) a
LEFT
JOIN
( SELECT x.* , COUNT(*) rank FROM changes x JOIN changes y ON y.id <= x.id GROUP BY x.id ) b
ON b.source_id = a.source_id
AND b.rank = a.rank - 1;
I think you want:
SELECT c.id,
c.source_id,
c.target_id,
c.value,
c.value - COALESCE(co.value, 0) delta
FROM changes c
LEFT JOIN (
SELECT ci.id, MAX(cio.id) prev_id
FROM changes ci
JOIN changes cio
ON cio.source_id = ci.source_id
AND cio.target_id = ci.target_id
AND cio.id < ci.id
GROUP BY ci.id
) link
ON link.id = c.id
LEFT JOIN changes co
ON co.id = link.prev_id
ORDER BY c.id
I have changed the logic slightly.
In your expected results, the first diff has gone from unknown (0?) to 1201 and is reported as a positive diff, but the second has gone from 1201 to 100 and is still reported as positive.
I have changed the name to delta, and given you the number required to move from the previous value to the new value. Obviously you can change this if you want to:
COALESCE(co.value-c.value, c.value) diff
which will get you the results you provided (with the diff 500 changed to -500, which I believe was a typo).

Add columns of two rows based on a condition in mysql

I have the following table structure:
+------+-------+-------+--------+
| mid | a | b | points |
+------+-------+-------+--------+
| 69 | 3137 | 13316 | 210 |
| 70 | 13316 | 3137 | 350 |
| 71 | 3497 | 13316 | 200 |
| 72 | 13316 | 3497 | 25 |
| 73 | 3605 | 13316 | 205 |
| 74 | 13316 | 3605 | 290 |
+------+-------+-------+--------+
I want to add the "points" values of two rows when "a" of row 1 = "b" of row 2 and "a" of row 2 = "b" of row 1.
The output needs to be something like this:
+------+-------+-------+--------+
| mid | a | b | points |
+------+-------+-------+--------+
| 69 | 3137 | 13316 | 560 |
| 71 | 3497 | 13316 | 225 |
| 73 | 3605 | 13316 | 495 |
+------+-------+-------+--------+
You can try it this way
SELECT t1.mid, t1.a, t1.b, t1.points + t2.points points
FROM table1 t1 JOIN table1 t2
ON t1.a = t2.b
AND t1.b = t2.a
AND t1.mid < t2.mid
or leveraging MySQL non-standard GROUP BY extension
SELECT mid, a, b, SUM(points) points
FROM
(
SELECT mid, a, b, points
FROM table1
ORDER BY mid
) q
GROUP BY LEAST(a, b), GREATEST(a, b)
Output:
| MID | A | B | POINTS |
|-----|------|-------|--------|
| 69 | 3137 | 13316 | 560 |
| 71 | 3497 | 13316 | 225 |
| 73 | 3605 | 13316 | 495 |
Here is SQLFiddle demo
If I've understood correctly then you want:
SELECT p1.mid, p1.a, p1.b, p1.points + p2.points points
FROM points p1
INNER JOIN points p2 ON p1.a = p2.b AND p1.b = p2.a
WHERE p1.mid < p2.mid
I have knocked it up in sql fiddle and gives the output that you want.