Equations in SQL (MySQL) - mysql

I have a table with a cost_maintence column that has cost for the entire year(52) weeks. I also have a table of renters, and a table of renter_units where there is a week_owned column that has the week number the renter rented. I am trying to figure out how I could calculate the cost for each renter. The equation I came up with is:
what each person owes = (cost_maintence/52) * #weeks each renter
rented
Is there any way I could get the value from a query?
create table renters(
id,
lname,
fname,
phone_num);
create table unit(
id,
unit_name,
unit_num,
cost_maintence);
create table renters_unit(
renters_id,
unit_id,
week_owned);
This is the query I came up with but I have no way of testing it out
select r.lname, r.fname, count(ru.week_owned),
sum(u.cost_maintence/52*count(ru.week_owned))
from renters r, renters_units ru, units u
where r.id = ru.renter_id
and ru.unit_id = u.id
and u.unit_name =unitname
and u.unit_num = unitnum
group by lname
order by lname,fname asc;

Here's an example. The inner query will get you amount owed per item, and the outer query sums that to find the total owed per person.
SELECT fname, SUM(owes) AS total_due
FROM (
SELECT r.fname,
r.id,
u.unit_name,
u.cost_maintence/52*COUNT(ru.week_owned) AS owes
FROM renters AS r
INNER JOIN renters_unit AS ru ON r.id = ru.renters_id
INNER JOIN unit AS u ON u.id = ru.unit_id
GROUP BY r.id, u.id
) AS t
GROUP BY id
Try it out with a SQLFiddle demo
Example Schema:
create table renters(
id int,
lname varchar(20),
fname varchar(20),
phone_num varchar(20));
create table unit(
id int,
unit_name varchar(30),
unit_num int,
cost_maintence int);
create table renters_unit(
renters_id int,
unit_id int,
week_owned int);
INSERT INTO renters VALUES (1, 'Peterson', 'Chaz', '8675309');
INSERT INTO unit VALUES (1, 'Skateboard', 1337, 52);
INSERT INTO unit VALUES (2, 'Flamethrower', 5432, 104);
INSERT INTO renters_unit VALUES (1, 1, 1);
INSERT INTO renters_unit VALUES (1, 1, 2);
INSERT INTO renters_unit VALUES (1, 1, 4);
INSERT INTO renters_unit VALUES (1, 2, 4);
INSERT INTO renters_unit VALUES (1, 2, 5);
By this, we can see that Chaz should owe $7 for the year (had a skateboard for 3 weeks at $1 per week, and a flamethrower for 2 weeks at $2 per week).
The inner query gives the following:
FNAME UNIT_NAME OWES
Chaz Skateboard 3
Chaz Flamethrower 4
And the outer:
FNAME TOTAL_DUE
Chaz 7

SELECT t.renters_id, SUM(u.cost_maintence)/52
FROM unit u JOIN renters_unit t ON t.unit_id = u.id
GROUP BY t.renters_id

Related

MySQL select row from one table with multiple rows in a second table and get array of multi row in selected row

i have one table containing "Client" information, and another including "Tickets" information for each client.
int-------| varchar -------| varchar
client_id | client_name | client_tickets
----------+----------------+--------------
1 | Title one | 1,2
2 | Title two | 2,3
Simplified tickets table
int--------| varchar -------| varchar
ticket_id | ticket_name | ticket_price
-----------+-------------+--------------
1 | ticketone | 30
2 | tickettwo | 40
3 | ticketthree | 50
4 | ticketfour | 60
5 | ticketfive | 70
With the above two tables, I want to produce a single table with a single query with all the pertinent information to generate a search grid
So as to give the following output :
client_id | client_name | client_tickets | ticket_names | ticket_prices
----------+----------------+----------------+-----------------------+--
1 | Title one | 1,2 | ticketone,tickettwo | 30,40
2 | Title two | 2,3 | tickettwo,ticketthree | 40,50
ticket_names,ticket_ids,client_name are varchar
I want to receive the final 5 columns with one request
for example :
SELECT s.*,
(SELECT GROUP_CONCAT(ticket_name SEPARATOR ',') FROM tickets_table WHERE ticket_id IN(s.client_tickets)) AS ticket_names,
(SELECT GROUP_CONCAT(ticket_price SEPARATOR ',') FROM tickets_table WHERE ticket_id IN(s.client_tickets)) AS ticket_prices
FROM client_table s where s.client_id=1
Which seems to have a problem
Do you have a better suggestion?
Please make your suggestions
Update :
To clean the result I want
The following code has two querys,
I want this code to be done with a query
$client_result = $conn->query("SELECT * FROM client_table where client_id=1");
while($client_row = $client_result->fetch_assoc()) {
$ticket_result = $conn->query("SELECT * FROM tickets_table where ticket_id IN ($client_row['client_tickets'])");
while($ticket_row = ticket_result->fetch_assoc()) {
echo $ticket_row['ticket_name']."<br>";
}
}
update 2
i use suggest #raxi , but my mariadb is 10.4.17-MariaDB and don't support JSON_ARRAYAGG , for resolve it according to the reference Creating an aggregate function
, Using SQL
DELIMITER //
DROP FUNCTION IF EXISTS JSON_ARRAYAGG//
CREATE AGGREGATE FUNCTION IF NOT EXISTS JSON_ARRAYAGG(next_value TEXT) RETURNS TEXT
BEGIN
DECLARE json TEXT DEFAULT '[""]';
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN json_remove(json, '$[0]');
LOOP
FETCH GROUP NEXT ROW;
SET json = json_array_append(json, '$', next_value);
END LOOP;
END //
DELIMITER ;
What you want a fairly straightforward SELECT query with some LEFT/INNER JOIN(s).
This website has some good examples/explanations which seem very close to your need: https://www.mysqltutorial.org/mysql-inner-join.aspx
I would give you a quick working example, but it is not really clear to me what datatype the relevant columns are. Both tables' _id-columns are likely some variant of INTEGER, are they also both primary keys (or otherwise atleast indexed ?), the client_name/ticket_name are likely VARCHAR/TEXT/STRING types, but how exactly is the remaining column stored? as json or array or ? (+details)
Also you tagged your post with PHP, are you just after the SQL query ? or looking for PHP code with the SQL inside it.
updated
Improved version of the schema
CREATE TABLE clients (
client_id SERIAL,
client_name VARCHAR(255) NOT NULL,
PRIMARY KEY (client_id)
);
CREATE TABLE tickets (
ticket_id SERIAL,
ticket_name VARCHAR(255) NOT NULL,
ticket_price DECIMAL(10,2) NOT NULL,
PRIMARY KEY (ticket_id)
);
-- A junction table to glue those 2 tables together (N to N relationship)
CREATE TABLE client_tickets (
client_id BIGINT UNSIGNED NOT NULL,
ticket_id BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (client_id, ticket_id)
);
I have changed the datatypes.
client_name and ticket_name are still VARCHARS. I've flagged them as NOT NULL (eg: required fields), but you can remove that part if you don't like that.
client_id/ticket_id/ticket_price are also NOT NULL but changing that has negative side-effects.
ticket_price is now a DECIMAL field, which can store numbers such as 1299.50 or 50.00 The (10,2) bit means it covers every possible number up to 8 whole digits (dollars/euros/whatever), and 2 decimals (cents). so you can store anything from $ -99.999.999,99 to $ 99.999.999,99 .
in SQL always write numbers (like lets say 70k) in this notation: 70000.00 (eg: a dot, not a comma; and no thousandseperators).
client_id and ticket_id are both SERIALs now, which is shorthand for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE and theyre both PRIMARY KEYs on top of that. That probably sounds complicated but they're still just ordinary INTEGERs with values like 4 or 12 etc.
The UNIQUE bit prevents you from having 2 clients with the same ID number, and the AUTO_INCREMENT means that when you add a new client, you dont have to specify an ID (though you are allowed to); you can just do:
INSERT INTO clients (client_name) values ('Fantastic Mr Fox');
and the client_id will automatically be set (incrementing over time). And the same goes for ticket_id in the other table.
.
I've replaced your original client_tickets column, into a separate junction table.
Records in there store the client_id of a client and the ticket_id that belongs to them.
A client can have multiple records in the junction table (one record for each ticket they own).
Likewise, a ticket can be mentioned on any number of rows.
It's possible for a certain client_id to not have any records in the junction table.
Likewise, it's possible for a certain ticket_id to not have any records in the junction table.
Identical records cannot exist in this table (enforced by PRIMARY KEY).
Testdata
Next, we can put some data in there to be able to test it:
-- Create some tickets
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (1, 'ticketone', '30' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (2, 'tickettwo', '40' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (3, 'ticketthree', '50' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (4, 'ticketfour', '60' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (5, 'ticketfive', '70' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (6, 'ticketsix', '4' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (7, 'ticketseven', '9' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (8, 'ticketeight', '500' );
-- Create some users, and link them to some of these tickets
INSERT INTO clients (client_id, client_name) values (1, 'John');
INSERT INTO client_tickets (client_id, ticket_id) values (1, 3);
INSERT INTO client_tickets (client_id, ticket_id) values (1, 7);
INSERT INTO client_tickets (client_id, ticket_id) values (1, 1);
INSERT INTO clients (client_id, client_name) values (2, 'Peter');
INSERT INTO client_tickets (client_id, ticket_id) values (2, 5);
INSERT INTO client_tickets (client_id, ticket_id) values (2, 2);
INSERT INTO client_tickets (client_id, ticket_id) values (2, 3);
INSERT INTO clients (client_id, client_name) values (3, 'Eddie');
INSERT INTO client_tickets (client_id, ticket_id) values (3, 8);
INSERT INTO clients (client_id, client_name) values (9, 'Fred');
-- Note: ticket #3 is owned by both client #1/#2;
-- Note: ticket #4 and #6 are unused;
-- Note: client #9 (Fred) has no tickets;
Queries
Get all the existing relationships (ticket-less clients are left out & owner-less tickets are left out)
SELECT clients.*
, tickets.*
FROM client_tickets AS ct
INNER JOIN clients ON ct.client_id = clients.client_id
INNER JOIN tickets ON ct.ticket_id = tickets.ticket_id
ORDER BY clients.client_id ASC
, tickets.ticket_id ASC ;
Get all the tickets that are still free (owner-less)
SELECT tickets.*
FROM tickets
WHERE tickets.ticket_id NOT IN (
SELECT ct.ticket_id
FROM client_tickets AS ct
)
ORDER BY tickets.ticket_id ASC ;
Get a list of ALL clients (even ticketless ones), and include how many tickets each has and the total price of their tickets.
SELECT clients.*
, COALESCE(COUNT(tickets.ticket_id), 0) AS amount_of_tickets
, COALESCE(SUM(tickets.ticket_price), 0.00) AS total_price
FROM clients
LEFT JOIN client_tickets AS ct ON ct.client_id = clients.client_id
LEFT JOIN tickets ON ct.ticket_id = tickets.ticket_id
GROUP BY clients.client_id
ORDER BY clients.client_id ASC ;
Put all the juicy info together (owner-less tickets are left out)
SELECT clients.*
, COALESCE(COUNT(sub.ticket_id), 0) AS amount_of_tickets
, COALESCE(SUM(sub.ticket_price), 0.00) AS total_price
, JSON_ARRAYAGG(sub.js_tickets_row) AS js_tickets_rows
FROM clients
LEFT JOIN client_tickets AS ct ON ct.client_id = clients.client_id
LEFT JOIN (
SELECT tickets.*
, JSON_OBJECT( 'ticket_id', tickets.ticket_id
, 'ticket_name', tickets.ticket_name
, 'ticket_price', tickets.ticket_price
) AS js_tickets_row
FROM tickets
) AS sub ON ct.ticket_id = sub.ticket_id
GROUP BY clients.client_id
ORDER BY clients.client_id ASC ;
-- sidenote: output column `js_tickets_rows` (a json array) may contain NULL values
An list of all tickets with some aggregate data
SELECT tickets.*
, IF(COALESCE(COUNT(clients.client_id), 0) > 0
, TRUE, FALSE) AS active
, COALESCE( COUNT(clients.client_id), 0) AS amount_of_clients
, IF(COALESCE( COUNT(clients.client_id), 0) > 0
, GROUP_CONCAT(clients.client_name SEPARATOR ', ')
, NULL) AS client_names
FROM tickets
LEFT JOIN client_tickets AS ct ON ct.ticket_id = tickets.ticket_id
LEFT JOIN clients ON ct.client_id = clients.client_id
GROUP BY tickets.ticket_id
ORDER BY tickets.ticket_id ASC
, clients.client_id ASC ;

Sum sales from different tables

I have 5 tables related to sales. Three of them are like this:
Product_table_image
They are called product_a, product_b, product_c
The other tables are the time_id table which contains the reference for the date_id and the customers' table, which contains the details of customers.
time_id table
and
customer_table
The 3 tables refer to the sales of different products, but the products are not important in this context, because what I need is to sum up all the values per month per customer. There are cases when one or more customers might not have made a purchase of a certain product, which means not all customers ids will be in all products tables and that's what I can't figure out how to solve. It seems that my code is only able to fetch and sum when the clients have made purchases in all 3 tables.
So this is what I was able to come up with:
SELECT C.customer_id, ROUND((A.pa + B.pa + C.pc)* 1, 2) AS total,C.month_id
FROM (SELECT customer.customer_id, SUM(product_a.amount) AS pa , time_id.month_id FROM customer
INNER JOIN product_a on customer.customer_id = product_a.customer_id
INNER JOIN time_id on product_a.date_id = time_id.date_id
GROUP BY customer.customer_id, time_id.month_id) AS A
CROSS JOIN
(SELECT customer.customer_id, SUM(product_a.amount) AS pb , time_id.month_id FROM customer
INNER JOIN product_b on customer.customer_id = product_b.customer_id
INNER JOIN time_id on product_b.date_id = time_id.date_id
GROUP BY customer.customer_id, time_id.month_id) AS B
CROSS JOIN
(SELECT customer.customer_id, SUM(product_a.amount) AS pc , time_id.month_id FROM customer
INNER JOIN product_c on customer.customer_id = product_c.customer_id
INNER JOIN time_id on product_c.date_id = time_id.date_id
GROUP BY customer.customer_id, time_id.month_id) AS C
GROUP BY C.month_id, C.customer_id
ORDER BY C.month_id;
I've been stuck in it for a while, so any help is appreciated!
I have setup the tables and some sample data to make it more real.
create table month(id int, name varchar(20), primary key (id));
insert into month (id, name) values (1, 'January'),(2,'February'),(3,'March'),(4,'April');
create table year(id int, name varchar(4), primary key (id));
insert into year(id, name) values (2019, '2019'),(2020,'2020'),(2021,'2021');
create table time (id int, month_id int, year_id int, primary key (id));
alter table time add constraint fk_month FOREIGN KEY (month_id) REFERENCES month (id);
alter table time add constraint fk_year FOREIGN KEY (year_id) REFERENCES year (id);
insert into time (id, year_id, month_id) values
(1, 2019, 1),(2, 2019, 2),(3,2019,3),(4,2019,4),
(5, 2020, 1),(6, 2020, 2),(7,2020,3),(8,2020,4),
(9, 2021, 1),(10, 2021, 2),(11,2021,3),(12,2021,4);
create table customers (id int, name varchar(100), city varchar(100), country varchar(100), primary key (id));
insert into customers (id, name, city, country) values
(1, 'Google', 'San Francisco', 'US'),
(2, 'Ambev', 'São Paulo', 'BR'),
(3, 'Merck', 'Darmstadt', 'GE');
create table sales_of_product_a (id int, customer_id int, date_id int, amount decimal(10,2), primary key (id));
alter table sales_of_product_a add constraint fk_pa_time FOREIGN KEY (date_id) REFERENCES time (id);
-- only customer 1 - Google and 3 - Merck purchased product A
insert into sales_of_product_a (id, customer_id, date_id, amount) values
(1, 1, 1, 100.10),(2,1,2,200.20),(3,1,3,300.30),(4,1,4,400.40),
(5, 1, 5, 500.50),(6,1,6,600.60),(7,1,7,700.70),(8,1,8,800.80),
(9, 3, 1, 130.10),(10,3,2,230.20),(11,3,3,330.30),(12,3,4,430.40),
(13, 3, 5, 530.50),(14,3,6,630.60),(15,3,7,730.70),(16,3,8,830.80);
create table sales_of_product_b (id int, customer_id int, date_id int, amount decimal(10,2), primary key (id));
alter table sales_of_product_b add constraint fk_pb_time FOREIGN KEY (date_id) REFERENCES time (id);
-- only customer 1 - Google purchased product B
insert into sales_of_product_b (id, customer_id, date_id, amount) values
(1, 1, 1, 100.10),(2,1,2,200.20),(3,1,3,300.30),(4,1,4,400.40),
(5, 1, 5, 500.50),(6,1,6,600.60),(7,1,7,700.70),(8,1,8,800.80),
(9, 1, 9, 900.90),(10,1,10,1000.01),(11,1,11,1100.11),(12,1,12,1200.12);
create table sales_of_product_c (id int, customer_id int, date_id int, amount decimal(10,2), primary key (id));
alter table sales_of_product_c add constraint fk_pc_time FOREIGN KEY (date_id) REFERENCES time (id);
-- only customer 3 - Merck purchased product C
insert into sales_of_product_c (id, customer_id, date_id, amount) values
(1, 3, 1, 130.10),(2,3,2,230.20),(3,3,3,330.30),(4,3,4,430.40),
(5, 3, 5, 530.50),(6,3,6,630.60),(7,3,7,730.70),(8,3,8,830.80),
(9, 3, 9, 930.90),(10,3,10,1030.01),(11,3,11,1130.11),(12,3,12,1230.12);
The SQL you might be looking for would be something like.
with all_sales as (
select pa.customer_id, tt.month_id, sum(pa.amount) as amount from sales_of_product_a pa inner join time tt on (pa.date_id = tt.id) where tt.year_id = 2019 group by pa.customer_id, tt.month_id
union all
select pb.customer_id, tt.month_id, sum(pb.amount) as amount from sales_of_product_b pb inner join time tt on (pb.date_id = tt.id) where tt.year_id = 2019 group by pb.customer_id, tt.month_id
union all
select pc.customer_id, tt.month_id, sum(pc.amount) as amount from sales_of_product_c pc inner join time tt on (pc.date_id = tt.id) where tt.year_id = 2019 group by pc.customer_id, tt.month_id
),
sales_per_customer_per_month as (
-- summary of all sales of all products per customer per month
select customer_id, month_id, sum(amount) as amount from all_sales group by customer_id, month_id
),
customers_month as (
select c.id, c.name, c.city, c.country, m.id as month_id, m.name as month_name from customers c inner join month m on true
)
select c.id,c.name,c.city,c.country,c.month_id, coalesce(s.amount,0) as amount, sum(coalesce(s.amount,0)) over (partition by c.id order by c.id,c.month_id) as total
from customers_month c
left join sales_per_customer_per_month s on (s.customer_id = c.id and s.month_id = c.month_id)
order by c.id,c.month_id;
The result of query above is following.
The concepts used are linked below.
Window Functions:
https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
Common Table Expressions (CTE):
https://www.mysqltutorial.org/mysql-cte/

How to return multiple rows when using Aggregate functions?

SELECT StudentID, Fname, LName, S_LessonNumber, LessonName, Date, Cost
FROM STUDENT_2
JOIN LESSON ON S_LessonNumber = LessonNumber
NATURAL JOIN STUDENT_1
WHERE StudentID = '1001'
The resulting table I get with this query is as follows,
When attempting to display the total amount paid, and the total number of lessons taken, using the following query, I was only able return one row.
SELECT StudentID, Fname, LName, S_LessonNumber, LessonName, Date,
Cost,COUNT( DISTINCT S_LessonNumber ) , SUM( Cost )
FROM STUDENT_2
JOIN LESSON ON S_LessonNumber = LessonNumber
NATURAL JOIN STUDENT_1
WHERE StudentID = '1001'
Is there a way that I can return all 4 rows with the values for COUNT(DISTINCT S_LessonNumber) and SUM(Cost) repeated.
The desired output is as follows:
StudentID FName LName S_LessonNumber LessonName Date Cost COUNT SUM
1001 Hannibal Lecter 7 C--- --- 15 4 60
1001 Hannibal Lecter 6 Wa-- --- 15 4 60
1001 Hannibal Lecter 5 Tri-- --- 15 4 60
1001 Hannibal Lecter 1 Cha- --- 15 4 60
Aggregate functions will always return 1 row. If using subqueries is not a problem, you can do:
SELECT StudentID, Fname, LName, S_LessonNumber, LessonName, Date, Cost,
(SELECT COUNT( DISTINCT S_LessonNumber ) FROM STUDENT_2 JOIN LESSON ON S_LessonNumber = LessonNumber NATURAL JOIN STUDENT_1 WHERE StudentID = '1001') AS COUNT,
(SELECT SUM( Cost ) FROM STUDENT_2 JOIN LESSON ON S_LessonNumber = LessonNumber NATURAL JOIN STUDENT_1 WHERE StudentID = '1001') AS SUM
FROM STUDENT_2
JOIN LESSON ON S_LessonNumber = LessonNumber
NATURAL JOIN STUDENT_1
WHERE StudentID = '1001'
Check it here: http://rextester.com/SBUQ82088
create table if not exists fstudents (id int, fname text, lname text);
create table if not exists fstudents2 (student_id int, lesson_number int, lesson_date date, cost int);
create table if not exists flessons (number int, name text);
insert into fstudents values (1001, 'Anibal', 'Lecter');
insert into flessons values (1, 'Cha Cha');
insert into flessons values (2, 'Waltz');
insert into flessons values (3, 'Country');
insert into flessons values (4, 'Triple2');
insert into fstudents2 values (1001, 1, '2016-10-06', 15);
insert into fstudents2 values (1001, 2, '2016-10-07', 15);
insert into fstudents2 values (1001, 3, '2016-10-08', 15);
insert into fstudents2 values (1001, 4, '2016-10-09', 15);
Use a subquery to count an sum, and then join it to main query.
select st2.student_id, st.fname, st.lname, ls.name, st2.lesson_date, st2.cost, agg.courses, agg.total_cost
from fstudents2 st2
join fstudents st on st2.student_id = st.id
join flessons ls on st2.lesson_number = ls.number
join (select st3.student_id, count(st3.lesson_number) courses, sum(st3.cost) total_cost
from fstudents2 st3
group by st3.student_id) agg on agg.student_id = st2.student_id
where
st2.student_id = 1001;

MYSQL - Updating count in one tabled based on two other tables joined

I have 3 related tables. Adults, Children and AC. Adults contains an INT column to count high school seniors. Children contains a column with year of highs school graduation. AC links the adult.id to the children.id.
CREATE TABLE adults (
id INT,
name VARCHAR(10),
seniors INT DEFAULT 0
) ;
INSERT INTO adults (id, name) VALUES
(1, 'adam'),
(2, 'bob');
CREATE TABLE children (
id INT,
name VARCHAR(10),
grad VARCHAR(4)
) ;
INSERT INTO children (id, name, grad) VALUES
(1, 'sally', '2016'),
(2, 'johnny', '2017'),
(3, 'eric', '2016'),
(4, 'billy', '2016'),
(5, 'rachel', '2016');
CREATE TABLE pc (
id INT,
a_id INT,
c_id INT
) ;
INSERT INTO pc (id, a_id, c_id) VALUES
(1, 1, 1),
(2, 1, 2),
(3, 1, 3),
(4, 2, 3),
(5, 2, 2);
SQLFiddle: http://sqlfiddle.com/#!2/89281e
So I want to update adults.seniors to the count of '2016' children they're linked to. So adult #1 would be "2" (sally and eric), and adult #2 "1" (eric).
The real data will be run across 25,000+ children being matched up to 40,000+ parents with a row count on the "pc" table above 3,000,000 rows - so looking for efficiency. I started working down this path but a) it's not working for obvious reasons and b) I doubt it would be efficient...
UPDATE adults a SET
seniors = (
SELECT p.a_id, count(*)
FROM pc p
INNER JOIN children c ON c.id = p.c_id
WHERE c.grad = '2016'
GROUP BY p.c_id)
WHERE p.a_id = a.id;
I'm thinking there has to be a better way of doing this with joins but can't seem to wrap my head around it.
You should be looking for this update statement:
UPDATE adults a
JOIN
(SELECT
p.a_id, COUNT(*) childrencount
FROM
pc p
INNER JOIN children c ON c.id = p.c_id
WHERE
c.grad = '2016'
GROUP BY p.a_id) c ON (a.id = c.a_id)
SET
seniors = c.childrencount;

SQL Product Group Size & Colors Together

I have following 3 tables, which I want to use to group 2 rows together to make it as single row, because they belong to one product.
Order
--------
order_id
Order_product
-------------
order_id
order_product_id
order_product_attribute
------------------------------
orders_products_attributes_id
order_id
product_id
products_options
options_id
=== Data ===
|1|2|7|Size |1|270
|2|2|7|Colour(s) |3|99202
|3|2|8|Size |1|270
|4|2|8|Colour(s) |3|47768
My desire result needs to be following:
order_id, product_id, size_options_id (option_id for size), colour_options_id (option_id for color)
size_options_id is optional, which means it might not even exist for some products.
I'm not sure what join I need to use to get this result in one go, rather then doing it from PHP checks.
Assuming that your tables are as follows:
create table order (order_id int);
insert into order values(2);
create table order_product (order_id int, order_product_id int);
insert into order_product values (2,7);
insert into order_product values (2,8);
create table order_product_attribute (orders_products_attributes_id int, order_id int, product_id int, products_options int, options_id int);
insert into order_product_attribute values (1, 2, 7, 1, 270);
insert into order_product_attribute values (2, 2, 7, 3, 99202);
insert into order_product_attribute values (3, 2, 8, 1, 270);
insert into order_product_attribute values (4, 2, 8, 3, 47768);
desired output:
2 7 270 99202
2 8 270 47768
You should use two left joins. It should be something like:
select
o.order_id,
op.product_id,
opas.options_id as size_options_id,
opac.options_id as colour_options_id
from my_order o
join order_product op on op.order_id=o.order_id
left join order_product_attribute opas
on opas.order_id=o.order_id
and opas.product_id=op.product_id
and opas.product_options=1
left join order_product_attribute opac
on opac.order_id=o.order_id
and opac.product_id=op.product_id
and opac.product_options=3
First left join is joining only with these rows which contain sizes.
Second left join is joining with rows containing colors.
You can see it in SQLFiddle