Sum SQL Values Based On 20 Tables - mysql

I have 20 tables with same column with several example as below :
Australian GP
DRIVER | Points
================
HAM | 25
VET | 20
RIC | 15
Japanese GP
Driver | Points
==============
HAM | 25
VET | 20
RIC | 15
Malaysian GP
Driver | Points
RIC | 25
HAM | 20
VET | 15
I am planning to join all the 20 tables and all 20 driver datas as below for example :
Championship Standings
Driver | Points
HAM | 70
VET | 65
RIC | 50
Based on intense googling and massive confusion (I am bad at SQL since I have no spare time to learn outside my college), I have conclusion to use inner join and subquery such as below (which I don't know is it correct or a laughstock):
select driverid, point
from usa a, russia b, japan c
inner join (select driverid as Driver, sum(point) group by points);
I also thought that do I have to write 20 inner joins (as per example below) to connect the driver values between the tables?
(I created a table for Driver which contains driverid as primary key. All table that used to write points use foreign key from driver table)
Really really appreciate any helps regarding this case

You want union all`:
select driver, sum(points)
from ((select driver, points from usa) union all
(select driver, points from russia) union all
. . .
) c
group by driver;

Try this:
Select * From Table1
UNION ALL
Select * From Table2
UNION ALL
Select * From Table3
.
.
.
GROUP BY Driver
Where Table1, Table2, Table3 and so on are the names of your actual tables

Related

UNION, SUM and count(*) together in PHP SQL query

So I have php SQL query that queries the floors and the total workstations on each floor.
config_location_workstation workstation asset_inventory
floor floor floor
workstation_number workstation_number workstation_number
workstation_name assigned_user
(production|non-production) machine_type
I have config_location_workstation table that consist of floor, workstation_number, workstation_name (Production, Non-Production).
Then, I have asset_workstation table that consist of floor, workstation_number, assigned_user, machine_type (Laptop, Desktop). workstation_number has all the users workstation number per floor.
I also have asset_inventory table that also has floor and workstation_number of each machine.
I was able to query the total count of workstations per floor. But I also need to pull up all the workstation_name that has 'Production' in it. I need to combine all the tables to produce one query to get the total count of each workstation, machines deployed to each floor, total head count per floor. I need to get the count of all users workstation number per workstation_name (Production, Non-Production).
This is the current code I have to pull up the floors and the total workstations.
$query=mysqli_query($conn,"SELECT workstation.floor, COUNT(*) TOTAL FROM ( SELECT floor FROM config_location_workstation UNION ALL SELECT floor FROM asset_workstation ) AS workstation GROUP BY floor ORDER BY floor");
I am expecting to output
+-------+-------------+------+------+------+------+-----+
| Floor | Head Count | Workstations| Machines Deployed |
+-------+-------------+------+------+------+------+-----+
| 6TH | 100 | 150 | 140 |
| 18TH | 200 | 250 | 200 |
| 19TH | 300 | 320 | 310 |
+-------+-------------+------+------+------+------+-----+
How am I going to do this in one query.
Your tables are not normalized: there appears to be duplicate information in all 3 tables. (unless workstation_number is not unique and floor/workstation_number is a composite key. I would advise against that...)
I would suggest a schema similar to this (assuming a many-to-many relationship between users and workstations):
Workstation User_Workstation User
id <- - workstation_id
workstation_number user_id - -> id
machine_type name
name
floor
Each of the fields in Workstation describe an attribute of a workstation. Any information you may have gathered from the other two tables is now in one place. Don't Repeat Yourself! Duplicate data is evil.
The goal is
I need to combine all the tables to produce one query to get the
total count of each workstation,
machines deployed to each floor,
total head count per floor.
I need to get the count of all users workstation number per workstation_name (Production, Non-Production).
Individually, these are a piece of cake. (And, if you're running a script to get your results, it's all you need)
select count(id) number_of_workstations
from Workstation;
select count(id) workstations_per_floor, floor
from Workstation
group by floor
select count(u.id) users_per_floor, floor
from Workstation w
inner join User_Workstation uw on w.id = uw.workstation_id
inner join User u on u.id = uw.user_id
-- optionally filter by production or non-production
-- where w.name = ?
group by w.floor
But your desired result seems to be something different:
+-------+-------------+------+------+------+------+-----+
| Floor | Head Count | Workstations| Machines Deployed |
+-------+-------------+------+------+------+------+-----+
| 6TH | 100 | 150 | 140 |
| 18TH | 200 | 250 | 200 |
| 19TH | 300 | 320 | 310 |
+-------+-------------+------+------+------+------+-----+
I'm guessing that Head Count is number of users per floor, Workstations is total workstations per floor, and Machines Deployed is... I have no idea. Production?
select floor, count(u.id) Head_Count, count(distinct w.id) Workstations, -- ??? as Machines_Deployed
from workstation w
left join user_workstation uw on w.id = uw.workstation_id
left join user on u.id = uw.user_id
group by w.floor
(I'll modify this based on feedback on what Machines Deployed is)

How do I sum a column, and join it to another table based on a condition in SQL?

I have two tables in SQL, one that contains product_id, products_name, department_name, and product_sales and one that has department_id, department_name, and over_head_costs.
I want to be able to find the sum of all sales (grouped by department_name in table 1) and subtract the over_head_costs from table 2 so that I know how profitable a department is. Then I want to output the information like:
department_id, department_name, over_head_costs, product/department sales, total_profit.
I've been searching for like 2-3 hours. I've messed around with joins (which I'm pretty sure is how to solve this) and found the SUM function, which achieves summing (but not by department) and honestly, even if I'd seen the solution I wouldn't know it. I'm just really struggling to understand SQL.
SELECT SUM(products.product_sales), department_id, departments.department_name, over_head_costs
FROM products, departments
WHERE products.department_name = departments.department_name;
This is my most recent query and the closest I've gotten, except it only returns one department (I currently have 3).
This is roughly what I’d like it to look like:
Table 1 (products):
ID ITEM DEPARTMENT SALES
1 Hammer Tools 40
2. Nails Tools 40
3. Keyboard Computer 80
Table 2 (departments):
ID DEPARTMENT COST
1 Tools 20
2. Computer 30
Output:
ID DEPARTMENT COST SALES PROFIT
1 Tools 20 80 60
2. Computer 30 80 50
I'm not really sure what else to try. I think I'm just not understanding how joins and such work. Any help would be greatly appreciated.
You can try to use SUM wiht group by in a subquery. then do join.
Query 1:
SELECT d.*,
t1.SALES,
(t1.SALES - d.COST)PROFIT
FROM (
SELECT DEPARTMENT,SUM(SALES) SALES
FROM products
GROUP BY DEPARTMENT
) t1 JOIN departments d on d.DEPARTMENT = t1.DEPARTMENT
Results:
| DEPARTMENT | COST | SALES | PROFIT |
|------------|------|-------|--------|
| Tools | 20 | 80 | 60 |
| Computer | 30 | 80 | 50 |

Querying table with dates in SQL

I need to query a MySQL database table that looks like this:
Bike Owner Date
-----------------------
1 Oscar 2014-02-02
2 Oscar 2014-02-02
3 John 2014-04-28
4 Jane 2014-05-29
2 John 2015-04-16
3 Mike 2015-06-16
1 Bob 2015-07-16
4 John 2015-08-16
2 Mike 2016-04-16
3 John 2016-04-16
It contains 4 bikes and as soon as the bike switches from owner, a new record is placed within this table. Since this table doesn't have an 'until' attribute, I am stuck creating a query that gets all the owners of all bikes at a specific date, say 2015-07-06.
Does anyone now how to do this in an easy way? I can think of ways of doing this by creating functions or temporary tables, but this seems way too far fetched for such an easy question.
Thanks!
One method uses an explicit join and aggregation:
select b.*
from (select bike, max(date) as maxdate
from bikes b
where date <= '2015-07-06
group by bike
) bd join
bikes b
on b.bike = bd.bike and b.date = bd.maxdate;
A somewhat shorter way to write this:
select b.*
from bikes b
where b.date = (select max(b2.date) from bikes b2 where b2.bike = b.bike);
If I understood your requirement correctly then it is very straight foreword query, getting all owner of bike on specific date
select b.*
from bikes b
where CAST(b.date AS DATE) = '2015-07-06'

Select a DISTINCT ID, then pull data from another table

I have 2 MySQL tables, one for parts, and one for years. I can't figure out how to make a table on stackoverflow.. keeps making headers so here's my weak attempt to explain what I need.
Table 1
id | part_id | years
====================
0 | 15 | 1945
1 | 15 | 1946
2 | 16 | 1944
3 | 16 | 1947
4 | 16 | 1948
5 | 17 | 1953
As you may have guessed, part_id is the id number of the part in the parts table. Now, I know I have this to pull out a distinct part id, based on the year. That part is easy.
SELECT DISTINCT part_id FROM `years` WHERE year BETWEEN 1945 AND 1949
This is just an example, but that works exactly like I want it to. Gives me
15 and 16. Just one time. Which is great.
Now, do I need to do a loop in php to get the information from parts? I'm not sure how to do a join here.
<?php
foreach($item_pulled_from_db as $newid) {
$query = "SELECT * FROM 'parts' WHERE id = $newid";
} // I know there's more stuff to do in here, just a basic overview for you to look at
?>
Should I do the above code? Is there a way to select a DISTINCT part_id and then pull the data from another table for that ID in MySQL? Or do I have to do a loop like this?
Edit: I hope this isn't too confusing of a question. I'm not very good with words, which is why I like to program. :)
Use a join:
SELECT parts.*
FROM parts
JOIN (SELECT DISTINCT part_id
FROM years
WHERE year BETWEEN 1945 AND 1949) years
ON parts.id = years.part_id
You could pull this off using a JOIN in a single query. Try:
SELECT `parts`.* FROM `parts`
INNER JOIN `years` ON `years`.`part_id` = `parts`.`id`
WHERE `years`.`year` BETWEEN 1945 AND 1949
Execute that single query from PHP and then fetch the result set. It should be the same as what you would get using the multiple queries.
This query give you the result you want:
SELECT DISTINCT
p.*
FROM
years y
INNER JOIN
parts p ON p.id = y.part_id
WHERE
y.year BETWEEN 1945 AND 1949

Join derived table with itself

In short words:
I have events table:
[tbl]
time | newState
1200 | 1
1300 | 2
1400 | 5
I need to transform this table into intervals table [intervals]:
t0 | t1 | state
1200 | 1300 | 1
1300 | 1400 | 2
RESTRICTION: SQL COMPACT EDITION
the query:
SELECT leftPart.time AS t0, min(rightPart.time) AS t1, leftPart.newState
FROM tbl AS leftPart
LEFT OUTER JOIN tbl As rightPart
ON leftPart.time<rightPart.time
GROUP BY leftPart.Time,leftPart.newState
It works perfect when [tbl] is permanent table in database, but in my case [tbl] is derived from another select subquery! like this:
(SELECT time,newState
from ...) AS derivedTb
So, when i try something like this:
SELECT derivedTbl.time As t0,derivedTbl.state,min(rigthTblPart.time) FROM
(SELECT time,newState
from ...) AS derivedTbl
LEFT OUTER JOIN with derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time ...
It throws error: "derivedTbl does not exist"...
It seems that the derived table under it's alias is not visible to higher level query (thanks, google translator! ))...
Is there any way to store derived tables in query and using them in different parts of query? SQL CE doesn't support temporary tables, views and common table expressions...
task details (if interesting):
i have 2 tables of events:
[states1]
time | state1
1200 | 1
1300 | 2
1400 | 3
[states2]
time | state2
1200 | 0
1230 | 10
1330 | 20
1430 | 30
I need convert them in intervals table:
[intervals]
t0 t1 state1 state2
1200 1230 1 0
1230 1300 1 10
1300 1330 2 10
1330 1400 2 20
1400 1430 3 20
1430 NULL 3 30
stages of convertion:
1. overall timeline
(SELECT Time FROM States1
UNION
SELECT Time FROM States2) AS timetbl
join states1 table
join states2 table
for this moment all goes well:
SELECT states12tbl.time, states12tbl.state1, states2tbl.State AS state2
FROM (SELECT states12tbl_1.time, states12tbl_1.state1, MAX(states2tbl.Time) AS states2time
FROM (SELECT timetbl.time, states1tbl.State AS state1
FROM (SELECT timetbl_1.Time AS time, MAX(States1tbl.Time) AS state1time
FROM (SELECT Time
FROM States1
UNION
SELECT Time
FROM States2) AS timetbl_1 LEFT OUTER JOIN
States1 AS States1tbl ON States1tbl.Time <= timetbl_1.Time
GROUP BY timetbl_1.Time) AS timetbl INNER JOIN
States1 AS states1tbl ON timetbl.state1time = states1tbl.Time
join table with itself... and here is problem, i need to join code(3) with itself, because sql ce can't remember temp tables... If you have some better idea, please, share :)
Create a VIEW based on your first SELECT.
Onotole, I think that this WITH is making the trouble.
rewrite this query like
SELECT
derivedTbl.time As t0,
derivedTbl.state,
min(rigthTblPart.time)
FROM
(SELECT time,newState from ...) AS derivedTbl
LEFT OUTER JOIN derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time
....