MySQL: Matching columns for year over year - mysql

This is a repost to help clarify my question. I am working with time series data and I need to reference a previous year's data. In excel I would just use a vlookup or index match.
Here is my table
+------------+--------------+--------------+------+-------+
| date | unique_id | prev_year_id | id | value |
+------------+--------------+--------------+------+-------+
| 2016-01-01 | 1-2016-01-01 | 1-2015-01-01 | 1 | 7 |
| 2016-01-01 | 2-2016-01-01 | 2-2015-01-01 | 2 | 19 |
| 2016-01-01 | 3-2016-01-01 | 3-2015-01-01 | 3 | 6 |
| 2016-01-01 | 4-2016-01-01 | 4-2015-01-01 | 4 | 13 |
| 2016-01-01 | 5-2016-01-01 | 5-2015-01-01 | 5 | 5 |
| 2017-01-01 | 1-2017-01-01 | 1-2016-01-01 | 1 | 17 |
| 2017-01-01 | 2-2017-01-01 | 2-2016-01-01 | 2 | 8 |
| 2017-01-01 | 3-2017-01-01 | 3-2016-01-01 | 3 | 20 |
| 2017-01-01 | 4-2017-01-01 | 4-2016-01-01 | 4 | 3 |
| 2017-01-01 | 5-2017-01-01 | 5-2016-01-01 | 5 | 0 |
| 2018-01-01 | 1-2018-01-01 | 1-2017-01-01 | 1 | 4 |
| 2018-01-01 | 2-2018-01-01 | 2-2017-01-01 | 2 | 21 |
| 2018-01-01 | 3-2018-01-01 | 3-2017-01-01 | 3 | 7 |
| 2018-01-01 | 4-2018-01-01 | 4-2017-01-01 | 4 | 3 |
| 2018-01-01 | 5-2018-01-01 | 5-2017-01-01 | 5 | 6 |
+------------+--------------+--------------+------+-------+
my columns are:
date,
unique_id (this is the concat of id and date together; primary key),
prev_year_id (concat of id and date - interval 1 year),
id,
value
I need help making a statement to match the prev_year_id to the unique_id and return the value of the rows.
There will be a gap of the first year since there will not be any data to reference, but beyond the first year each prev_year_value will have a match to it's previous year's unique_id
This is what I imagine the end result looking like:
+------------+--------------+--------------+------+-------+-----------------+
| date | unique_id | prev_year_id | id | value | prev_year_value |
+------------+--------------+--------------+------+-------+-----------------+
| 2016-01-01 | 1-2016-01-01 | 1-2015-01-01 | 1 | 7 | null |
| 2016-01-01 | 2-2016-01-01 | 2-2015-01-01 | 2 | 19 | null |
| 2016-01-01 | 3-2016-01-01 | 3-2015-01-01 | 3 | 6 | null |
| 2016-01-01 | 4-2016-01-01 | 4-2015-01-01 | 4 | 13 | null |
| 2016-01-01 | 5-2016-01-01 | 5-2015-01-01 | 5 | 5 | null |
| 2016-01-01 | 1-2017-01-01 | 1-2016-01-01 | 1 | 17 | 7 |
| 2016-01-01 | 2-2017-01-01 | 2-2016-01-01 | 2 | 8 | 19 |
| 2016-01-01 | 3-2017-01-01 | 3-2016-01-01 | 3 | 20 | 6 |
| 2016-01-01 | 4-2017-01-01 | 4-2016-01-01 | 4 | 3 | 13 |
| 2016-01-01 | 5-2017-01-01 | 5-2016-01-01 | 5 | 0 | 5 |
| 2016-01-01 | 1-2018-01-01 | 1-2017-01-01 | 1 | 4 | 17 |
| 2016-01-01 | 2-2018-01-01 | 2-2017-01-01 | 2 | 21 | 8 |
| 2016-01-01 | 3-2018-01-01 | 3-2017-01-01 | 3 | 7 | 20 |
| 2016-01-01 | 4-2018-01-01 | 4-2017-01-01 | 4 | 3 | 3 |
| 2016-01-01 | 5-2018-01-01 | 5-2017-01-01 | 5 | 6 | 0 |
+------------+--------------+--------------+------+-------+-----------------+
And this is the statement I have..
SELECT A.*, B.value as 'prev_year_value'
FROM table1 A
INNER JOIN table1 B ON A.current_month_code = B.`prev_year_code
The results are very slow to return and it returns the next year's value, not the previous year.

SELECT a.*, b.`value` as `prev_year_value`
FROM `table1` a
LEFT JOIN `table1` b
ON a.`prev_year_id` = b.`unique_id`
Since this is a left join, if there is no result for the "ON" statement, the results will still include the values from a, and the prev_year_value will end up being null, as you want.
In inner joins like the one you tried, it will only include results, where there is a matchup in both tables

Related

Mysql Finding Aggregate Between Two Other Values

I'm working with a pretty nasty table schema which unfortunately I can't change as it's defined by our SCADA program. There's one analog float value (power usage), and one digital int value (machine setting). I need to be able to find the Min, Max, and Avg of the power usage for each machine setting.
So basically each time a new machine setting (intvalue) is recorded, I need the aggregate power usage (floatvalue) until the next machine setting. I'd like to be able to group by intvalue as well, so I could get these aggregate numbers for a whole month, for example.
So far, I've tried playing around with joins and nested queries, but I can't get anything to work. I can't really find any examples like this either, since its such a poor table design.
Table schema found here: http://www.sqlfiddle.com/#!9/29164/1
Data:
| tagid | intvalue | floatvalue | t_stamp |
|-------|----------|------------|----------------------|
| 2 | 9 | (null) | 2019-07-01T00:01:58Z |
| 1 | (null) | 120.2 | 2019-07-01T00:02:00Z |
| 1 | (null) | 120.1 | 2019-07-01T00:02:31Z |
| 2 | 11 | (null) | 2019-07-01T00:07:58Z |
| 1 | (null) | 155.9 | 2019-07-01T00:08:00Z |
| 1 | (null) | 175.5 | 2019-07-01T00:10:12Z |
| 1 | (null) | 185.5 | 2019-07-01T00:10:58Z |
| 2 | 2 | (null) | 2019-07-01T00:11:22Z |
| 1 | (null) | 10.1 | 2019-07-01T00:11:22Z |
| 1 | (null) | 12 | 2019-07-01T00:13:58Z |
| 1 | (null) | 9.9 | 2019-07-01T00:14:21Z |
| 2 | 9 | (null) | 2019-07-01T00:15:38Z |
| 1 | (null) | 120.9 | 2019-07-01T00:15:39Z |
| 1 | (null) | 119.2 | 2019-07-01T00:16:22Z |
Desired output:
| intvalue | min | avg | max |
|----------|-------|-------|-------|
| 2 | 9.9 | 10.7 | 12 |
| 9 | 119.2 | 120.1 | 120.9 |
| 11 | 155.9 | 172.3 | 185.5 |
Is this possible?
You can fill the missing intvalues with a subquery in the SELECT clause:
select t.*, (
select t1.intvalue
from sqlt_data_1_2019_07 t1
where t1.t_stamp <= t.t_stamp
and t1.intvalue is not null
order by t1.t_stamp desc
limit 1
) as group_int
from sqlt_data_1_2019_07 t
order by t.t_stamp;
The result will be
| tagid | intvalue | floatvalue | t_stamp | group_int |
| ----- | -------- | ---------- | ------------------- | --------- |
| 2 | 9 | | 2019-07-01 00:01:58 | 9 |
| 1 | | 120.2 | 2019-07-01 00:02:00 | 9 |
| 1 | | 120.1 | 2019-07-01 00:02:31 | 9 |
| 2 | 11 | | 2019-07-01 00:07:58 | 11 |
| 1 | | 155.9 | 2019-07-01 00:08:00 | 11 |
| 1 | | 175.5 | 2019-07-01 00:10:12 | 11 |
| 1 | | 185.5 | 2019-07-01 00:10:58 | 11 |
| 2 | 2 | | 2019-07-01 00:11:22 | 2 |
| 1 | | 10.1 | 2019-07-01 00:11:22 | 2 |
| 1 | | 12 | 2019-07-01 00:13:58 | 2 |
| 1 | | 9.9 | 2019-07-01 00:14:21 | 2 |
| 2 | 9 | | 2019-07-01 00:15:38 | 9 |
| 1 | | 120.9 | 2019-07-01 00:15:39 | 9 |
| 1 | | 119.2 | 2019-07-01 00:16:22 | 9 |
Now you can simply group by the result of the subquery:
select (
select t1.intvalue
from sqlt_data_1_2019_07 t1
where t1.t_stamp <= t.t_stamp
and t1.intvalue is not null
order by t1.t_stamp desc
limit 1
) as group_int,
min(floatvalue) as min,
avg(floatvalue) as avg,
max(floatvalue) as max
from sqlt_data_1_2019_07 t
group by group_int
order by group_int;
And you get:
| group_int | min | avg | max |
| --------- | ----- | ------------------ | ----- |
| 2 | 9.9 | 10.666666666666666 | 12 |
| 9 | 119.2 | 120.10000000000001 | 120.9 |
| 11 | 155.9 | 172.29999999999998 | 185.5 |
View on DB Fiddle

Creating a log having the date of purchase

I need to create a log having the purchase date of an item.
Items can be owned by only one buyer at time. So, for example, if item1 was purchased by buyer2 in 2009 and after by buyer1 in 2015, then between 2009 and 2015 was owned by buyer2.
Here is my table:
+--------+------------+-----------+----------+
| id_doc | date | id_item | id_buyer |
+--------+------------+-----------+----------+
| 11 | 2016-06-07 | 1 | 4 |
| 10 | 2016-06-06 | 1 | 4 |
| 1 | 2015-11-30 | 1 | 1 |
| 9 | 2009-01-01 | 1 | 2 |
| 4 | 2001-01-12 | 1 | 2 |
| 8 | 1996-06-06 | 1 | 2 |
| 3 | 1995-05-29 | 1 | 1 |
| 2 | 1998-05-23 | 2 | 2 |
| 7 | 2014-10-10 | 3 | 2 |
| 6 | 2003-12-12 | 3 | 3 |
| 5 | 1991-01-12 | 3 | 2 |
+--------+------------+-----------+----------+
Here is a kind of table/view I need:
+------------+------------+-----------+----------+--------+
| date_from | date_to | id_item | id_buyer | id_doc |
+------------+------------+-----------+----------+--------+
| 2016-06-07 | - | 1 | 4 | 11 |
| 2016-06-06 | 2016-06-07 | 1 | 4 | 10 |
| 2015-11-30 | 2016-06-06 | 1 | 1 | 1 |
| 2009-01-01 | 2015-11-30 | 1 | 2 | 9 |
| 2001-01-12 | 2009-01-01 | 1 | 2 | 4 |
| 1996-06-06 | 2001-01-12 | 1 | 2 | 8 |
| 1995-05-29 | 1996-06-06 | 1 | 1 | 3 |
| 1998-05-23 | - | 2 | 2 | 2 |
| 2014-10-10 | - | 3 | 2 | 7 |
| 2003-12-12 | 2014-10-10 | 3 | 3 | 6 |
| 1991-01-12 | 2003-12-12 | 3 | 2 | 5 |
+------------+------------+-----------+----------+--------+
I've tried a lot with GROUP BY, GROUP_CONCAT, trying to access next record date, etc ... but I can't found out how to solve the problem.
Thanks in advance.
I finally found out the solution only for past purchases.
SELECT
main.id_doc, main.id_item, main.date AS "date_from", bi.date AS "date_to", main.id_buyer
FROM
MyTable main, MyTable bi
WHERE
bi.id_doc =
(
SELECT sub.id_doc
FROM MyTable sub
WHERE sub.id_item = main.id_item AND sub.date > main.date ORDER BY sub.date ASC LIMIT 1
);

MySQL: Get everyday incremental data

I want to fetch the data from Table based on date but in an incremental way.
Suppose I have data like this which is grouped by date
| DATE | Count |
| 2015-06-23 | 10 |
| 2015-06-24 | 8 |
| 2015-06-25 | 6 |
| 2015-06-26 | 3 |
| 2015-06-27 | 2 |
| 2015-06-29 | 2 |
| 2015-06-30 | 3 |
| 2015-07-01 | 1 |
| 2015-07-02 | 3 |
| 2015-07-03 | 4 |
So the result should come like this
| DATE | Count| Sum|
| 2015-06-23 | 10 | 10 |
| 2015-06-24 | 8 | 18 |
| 2015-06-25 | 6 | 24 |
| 2015-06-26 | 3 | 27 |
| 2015-06-27 | 2 | 29 |
| 2015-06-29 | 2 | 31 |
| 2015-06-30 | 3 | 34 |
| 2015-07-01 | 1 | 35 |
| 2015-07-02 | 3 | 38 |
| 2015-07-03 | 4 | 42 |
You would join every other previous date on that date, and then sum the count on that
If you give me your table structure, I can make it run.
id, name, date_joined
SELECT counts.theCount, sum(counts.theCount), table.date_joined
FROM yourTable
LEFT JOIN
(SELECT count(*) as theCount, table.date_joined
FROM yourTable
GROUP BY table.date_joined
) as counts
ON
yourTable.date_joined> counts.date_joined
GROUP BY yourTable.date_joined

Picking out specific values from a group in MySQL

This seems like such a simple problem, but I can't find a good solution. I'm trying to select information from a slightly misformatted table. Basically, wherever sequence=0, the person_id should actually be a company_id. This company_id then applies to all the rows which have the same group_id.
Someone thought it was a good idea to format things this way instead of simply having a company_id column, but it makes trying to select by company very difficult. It would make my programming much easier to simply add this extra column, and fix the formatting.
I want to turn something like this:
+----------+------------+-----------+----------+
| group_id | date | person_id | sequence |
+----------+------------+-----------+----------+
| 1 | 2012-08-31 | 10 | 0 |
| 1 | 2012-08-31 | 11 | 1 |
| 1 | 2012-08-31 | 12 | 2 |
| 2 | 1999-04-16 | 10 | 0 |
| 2 | 1999-04-16 | 21 | 1 |
| 2 | 1999-04-16 | 22 | 2 |
| 2 | 1999-04-16 | 23 | 3 |
| 2 | 1999-04-16 | 24 | 4 |
| 3 | 2001-01-09 | 30 | 0 |
| 3 | 2001-01-09 | 31 | 1 |
| 3 | 2001-01-09 | 11 | 2 |
| 3 | 2001-01-09 | 12 | 3 |
+----------+------------+-----------+----------+
Into this:
+------------+----------+------------+-----------+----------+
| company_id | group_id | date | person_id | sequence |
+------------+----------+------------+-----------+----------+
| 10 | 1 | 2012-08-31 | 11 | 1 |
| 10 | 1 | 2012-08-31 | 12 | 2 |
| 10 | 2 | 1999-04-16 | 21 | 1 |
| 10 | 2 | 1999-04-16 | 22 | 2 |
| 10 | 2 | 1999-04-16 | 23 | 3 |
| 10 | 2 | 1999-04-16 | 24 | 4 |
| 30 | 3 | 2001-01-09 | 31 | 1 |
| 30 | 3 | 2001-01-09 | 11 | 2 |
| 30 | 3 | 2001-01-09 | 12 | 3 |
+------------+----------+------------+-----------+----------+
The only way I can think of how to achieve this is with nested SELECT statements, which are very inefficient considering I have about 100M rows. It's a one time fix though, so I don't mind letting it run overnight.
If you permanently want to change your table to include a company_id column then do this:
First alter the table and add the new column:
alter table your_table add company_id int;
Then update all rows to set the company to the person_id = 0 for the group:
UPDATE your_table a
JOIN your_table b ON a.group_id = b.group_id
SET a.company_id = b.person_id
WHERE b.sequence = 0;
And finally remove the rows with sequence = 0:
DELETE FROM your_table WHERE sequence = 0;
Sample SQL Fiddle
The end result will be:
| group_id | date | person_id | sequence | company_id |
|----------|------------|-----------|----------|------------|
| 1 | 2012-08-31 | 11 | 1 | 10 |
| 1 | 2012-08-31 | 12 | 2 | 10 |
| 2 | 1999-04-16 | 21 | 1 | 10 |
| 2 | 1999-04-16 | 22 | 2 | 10 |
| 2 | 1999-04-16 | 23 | 3 | 10 |
| 2 | 1999-04-16 | 24 | 4 | 10 |
| 3 | 2001-01-09 | 31 | 1 | 30 |
| 3 | 2001-01-09 | 11 | 2 | 30 |
| 3 | 2001-01-09 | 12 | 3 | 30 |

MySQL SUM() returning spurious (?) values

Despite spending an hour on this, the solution is eluding me still. I have a complex-ish query that is returning incorrect data for the SUM(). Yet, when I strip it down to the barest form, it outputs the correct data. But why and fix, I cannot figure out.
The Problem
SELECT po.*, SUM( poo.material_qty ) AS total_items_ordered, suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN purchase_orders_items poo ON poo.poid = po.poid
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC
Provides wildly incorrect data for 'total_items_ordered'.
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status | total_items_ordered | supplier_name |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised | 545 | John Parker & Son Ltd |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised | 80 | John Parker & Son Ltd |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
2 rows in set (0.00 sec)
And yet, when I strip all the complexities out of the query and run the raw SUM(), the value is correct:
mysql> SELECT poid, SUM(material_qty) AS total_items_ordered FROM `purchase_orders_items` GROUP BY poid;
+-------+---------------------+
| poid | total_items_ordered |
+-------+---------------------+
| 15571 | 109 |
| 15572 | 20 |
+-------+---------------------+
2 rows in set (0.00 sec)
Can anyone shed any light on where I'm going wrong here?? I've included all the test table content below just in case you can spot something I've missed. Thank you!
Data Example
mysql> SELECT * FROM purchase_orders;
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM purchase_orders_items;
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| poi_id | poid | material_id | material_qty | material_price | material_sku | material_name |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| 1 | 15571 | 2 | 3 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 2 | 15571 | 5 | 10 | 17.40 | 118-64-44 | Test Item (S275) |
| 3 | 15571 | 8 | 1 | 9984.50 | 113-64-21 | A really really really big universal beam (S355) |
| 4 | 15571 | 9 | 77 | 10.00 | 12345 | A thing |
| 5 | 15571 | 10 | 18 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
| 6 | 15572 | 2 | 6 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 7 | 15572 | 5 | 9 | 17.40 | 118-64-44 | Test Item (S275) |
| 8 | 15572 | 9 | 4 | 10.00 | 12345 | A thing |
| 9 | 15572 | 10 | 1 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
9 rows in set (0.00 sec)
mysql> SELECT * FROM suppliers;
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| supplier_id | supplier_name | supplier_telephone | supplier_fax | supplier_added_date | supplier_added_by | supplier_last_updated | supplier_last_updated_by | supplier_assessed | supplier_approved_by |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| 1 | John Parker & Son Ltd | 01227 783333 | 0800 521932 | 2014-05-04 15:57:43 | 1 | 2014-06-05 16:38:23 | 1 | 2014-05-04 15:57:43 | 2 |
| 2 | Superior Glass Ltd. | 01825 764766 | 01825 767699 | 2014-05-04 17:48:38 | 1 | 2014-06-04 20:14:16 | 1 | 2014-05-04 17:48:38 | 3 |
| 3 | DTS Origins Ltd. | 01283 3283029 | 01928 303494 | 2014-05-04 17:51:57 | 1 | 2014-05-04 17:53:08 | 1 | 2014-05-04 17:51:57 | 2 |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM materials_batch;
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| material_batch_id | poiid | rcvd_date | purchase_order_no | delivery_note_no | qty | rcvd_by | dn_scanned | material_id | supplier_id | batch_status |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| 1 | 1 | 0000-00-00 00:00:00 | 15571 | | 3 | 0 | No | 2 | 1 | Ordered |
| 2 | 2 | 0000-00-00 00:00:00 | 15571 | | 10 | 0 | No | 5 | 1 | Ordered |
| 3 | 3 | 0000-00-00 00:00:00 | 15571 | | 1 | 0 | No | 8 | 1 | Ordered |
| 4 | 4 | 0000-00-00 00:00:00 | 15571 | | 77 | 0 | No | 9 | 1 | Ordered |
| 5 | 5 | 0000-00-00 00:00:00 | 15571 | | 18 | 0 | No | 10 | 1 | Ordered |
| 6 | 6 | 0000-00-00 00:00:00 | 15572 | | 6 | 0 | No | 2 | 1 | Ordered |
| 7 | 7 | 0000-00-00 00:00:00 | 15572 | | 9 | 0 | No | 5 | 1 | Ordered |
| 8 | 8 | 0000-00-00 00:00:00 | 15572 | | 4 | 0 | No | 9 | 1 | Ordered |
| 9 | 9 | 0000-00-00 00:00:00 | 15572 | | 1 | 0 | No | 10 | 1 | Ordered |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
The reason for the wrong results should be clear when you leave out the GROUP BY from your query. For each table you JOIN, the number of returned rows is multiplied by the number of rows found by the JOIN.
As the materials_batch table contains multiple entries per order, the resulting total_items_ordered is multiplied by 5 for order number 15571, and its multiplied by 4 for order number 15572.
Try the following:
SELECT
po.*,
(
SELECT SUM(poo.material_qty)
FROM purchase_orders_items poo
WHERE poo.poid = po.poid
) AS total_items_ordered,
suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC