How to combine results from 2 queries without common "GROUP BY" element - mysql

I am trying to count the number of instances of different types and group them by a field denoting location. However, the location from my second query is obtained by a sub string of yet another field and is 300 less than the desired number.
The goal is to sum phone types by location. For IP phones (type 9608, b189, and 9611), the location is determined by the nr (network region). For analog devices (type cordless, 2500, and fax) the location is determined by the first 3 characters on the port.
I have each individual query working, for the most part, as desired. I have 2 issues:
The nr from the second query needs to have 300 added to the result.
I have not been able to combine the 2 queries together to obtain the desired, single result.
Example Data Set
+------+--------------+---------+-----------------------------+------+------+-----------+------+------+--------+-----------+------+----------------+------+
| id | extension | port | name | cp1 | cor | type | cp2 | cos | tenent | prod_id | tcp | ip | nr |
+------+--------------+---------+-----------------------------+------+------+-----------+------+------+--------+-----------+------+----------------+------+
| 62 | 111-000-0201 | S00215 | Baker Mail Rm | | 2 | 9608 | | 1 | 4 | IP_Phone | tcp | 172.20.94.76 | 308 |
| 63 | 111-000-0202 | S00216 | Baker Copy Rm | | 2 | 9608 | | 1 | 4 | | | | |
| 66 | 111-000-0205 | S00235 | Baker Conference Rm 2 | | 2 | b189 | | 1 | 4 | IP_Phone | tcp | 172.20.94.22 | 308 |
| 123 | 111-000-0626 | 008V301 | Baker Cordless | | 2 | cordless | | 1 | 1 | | | | |
| 145 | 111-000-1200 | S12329 | JEF-MAIN Dental 1 | | 2 | 9611 | | 1 | 1 | IP_Phone | tcp | 172.20.195.160 | 490 |
| 885 | 999-888-3025 | 190V203 | JEF WP Admin Conf Rm | | 2 | 2500 | | 1 | 1 | | | | |
| 890 | 999-888-1561 | 190V201 | JEF-GATO Clinic Fax | | 2 | fax | | 1 | 1 | | | | |
| 993 | 111-777-0202 | S00256 | Test Rm | | 2 | 9608 | | 1 | 4 | IP_Phone | | 172.20.190.45 | 303 |
| 994 | 111-777-0212 | S00217 | Test Rm 2 | | 2 | 9608 | | 1 | 4 | IP_Phone | | 172.20.190.46 | 303 |
Query 1
SELECT nr,
sum(type='9608') '9608',
sum(type='9611') '9611',
sum(type='b189') 'b189',
count(*) 'Total IP'
FROM station GROUP BY nr;
Result 1
+------+------+------+------+----------+
| nr | 9608 | 9611 | b189 | Total IP |
+------+------+------+------+----------+
| 308 | 1 | 0 | 1 | 2 |
| 490 | 0 | 1 | 0 | 1 |
| 303 | 2 | 0 | 0 | 2 |
Query 2
SELECT SUBSTR(port, 1, 3) AS 'nr',
sum(type='fax') 'fax',
sum(type='2500') 'analog',
sum(type='cordless') 'cordless',
count(*) 'Total Analog'
FROM station
WHERE port LIKE '___V%'
GROUP BY SUBSTR(port, 1, 3);
Result 2
+------+------+--------+----------+--------------+
| nr | fax | analog | cordless | Total Analog |
+------+------+--------+----------+--------------+
| 008 | 0 | 0 | 1 | 1 |
| 190 | 1 | 1 | 0 | 2 |
The desired result is
+------+------+------+------+----------+------+--------+----------+--------------+
| nr | 9608 | 9611 | b189 | Total IP | fax | analog | cordless | Total Analog |
+------+------+------+------+----------+------+--------+----------+--------------+
| 308 | 1 | 0 | 1 | 2 | 0 | 0 | 1 | 1 |
| 490 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 2 |
| 303 | 2 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |

Is this what you need? I used inner join. check my answer.
SELECT s1.nr,
sum(type='9608') '9608',
sum(type='9611') '9611',
sum(type='b189') 'b189',
count(*) 'Total IP' ,
fax,
analog,
cordless,
TotalAnalog
FROM station s1
INNER JOIN (
SELECT SUBSTR(port, 1, 3) AS 'nr',
sum(type='fax') 'fax',
sum(type='2500') 'analog',
sum(type='cordless') 'cordless',
count(*) 'TotalAnalog'
FROM station
WHERE port LIKE '___V%'
GROUP BY SUBSTR(port, 1, 3)
) as s2
ON s1.nr = s2.nr + 300
GROUP BY nr;
working Fiddle

Related

Is there any way I can sort a this table using 'ORDER BY'?

I have an 'accounts' table that contains a group account (isgroup) with subaccount (groupcode):
| code | title | groupcode | isgroup | groupindex |
|------|----------------|-----------|---------|------------|
| 100 | Current Assets | | 1 | 0 |
| 101 | Cash | 100 | 1 | 1 |
| 102 | AR | 100 | 1 | 1 |
| 103 | Property | | 1 | 0 |
| 104 | Balance | | 1 | 0 |
| 105 | Cash on hand | 101 | 1 | 2 |
| 106 | Cash in bank | 101 | 1 | 2 |
| 107 | My Bank 1 | 106 | 0 | 3 |
| 108 | Cahier 1 | 105 | 0 | 3 |
| 109 | Building 1 | 103 | 0 | 1 |
Notes:
There is no standard way to generate 'code'. It can be any (text)
Any account can have as many sub accounts determined by 'isgroup' and 'groupcode'.
'isgroup' determines if the account can have a sub account.
'groupindex' determines the sub account level. Index n(0) is the top level, its sub account will be in index n + 1
I need to sort it like this:
| code | title | groupcode | isgroup | groupindex |
|------ |---------------- |----------- |--------- |------------ |
| 100 | Current Assets | | 1 | 0 |
| 101 | Cash | 100 | 1 | 1 |
| 105 | Cash on hand | 101 | 1 | 2 |
| 108 | Cashier 1 | 105 | 0 | 3 |
| 106 | Cash in bank | 101 | 1 | 2 |
| 107 | My Bank 1 | 106 | 0 | 3 |
| 102 | AR | 100 | 1 | 1 |
| 103 | Property | | 1 | 0 |
| 109 | Building 1 | 103 | 0 | 1 |
| 104 | Balance | | 1 | 0 |
The top level account and its sub accounts up to n level must be displayed first, then the next top level account.
I've accomplished the task in application level using recursive function and add the rows one by one to a datatable. Is there any way I can sort this table in one query?

Grouping, yet concatenating values from within the group in MySQL

I have a simple MySQL table as such:
| CUST_ID | VISIT | PROD_ID |
|---------|-------|---------|
| 1 | 1 | 3473 |
| 1 | 2 | 324 |
| 1 | 2 | 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976 |
| 4 | 1 | 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
And I would like to transform it to this:
| CUST_ID | VISIT | PROD_IDs |
|---------|-------|----------|
| 1 | 1 | 3473 |
| 1 | 2 | 324, 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976, 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
This is kinda an ugly hack, I get it.
I have no idea how to cleanly create such a thing. I've tried a variety of unsuccessful grouping strategies. Even a clue or hint in the right direction would be great. Thanks.
If you're trying to group by cust_id + visit, then you can do that and use a GROUP CONCAT on the PROD_ID field, for example:
SELECT
CUST_ID,
VISIT,
GROUP_CONCAT(PROD_ID) PROD_IDS
FROM
table
GROUP BY
CUST_ID,
VISIT
Reference: GROUP CONCAT

MYSQL Union Operation with Gross, Cut & Net Amounts

I need to print Gross allocation, Cut Allocation & Net Allocation issued for various offices under relevant votes. I used the following tables.
1) Total issues (Gross Allocation) are in the Table, Named "issues_tot"
+---------+------+------------+
| v_code | oid | amount |
+---------+------+------------+
| 1 | 2 | 200,000.00 |
| 1 | 3 | 80,000.00 |
| 2 | 1 | 40,000.00 |
| 3 | 2 | 150,000.00 |
+---------+------+------------+
2) Cut amounts (Cut Allocation) are in the Table, Named "cp_tot"
+--------+-----+-----------+
| v_code | oid | amount |
+--------+-----+-----------+
| 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 3 | 2 | 75,000.00 |
+--------+-----+-----------+
3) Table, Named "vote"
+--------+-------------------------+
| v_code | vote |
+--------+-------------------------+
| 1 | 001-2-6-3-2502 |
| 2 | 001-1-4-21-2202 |
| 3 | 101-1-2-0-1405 |
+--------+-------------------------+
4) Table, Named "office"
+-----+----------------------+
| oid | office |
+-----+----------------------+
| 1 | Weeraketiya |
| 2 | Tissamaharama |
| 3 | District Sec |
+-----+----------------------+
And desired output as follows:
+--------+------------+-----------+------------+
| v_code | Gross | Cut | Net |
+--------+------------+-----------+------------+
| 1 | 200,000.00 | 68,000.00 | 132,000.00 |
| 1 | 80,000.00 | 50,000.00 | 30,000.00 |
| 2 | 40,000.00 | 0.00 | 40,000.00 |
| 3 | 150,000.00 | 75,000.00 | 75,000.00 |
+--------+------------+-----------+------------+
02) I used the following script to generate that output
select `vote`.`vote` AS `vote`,`office`.`office` AS `office`,
`issues_tot`.`amount` AS `Gross`,
coalesce(`cp_tot`.`amount`,0) AS `Cut`,
(`issues_tot`.`amount` - coalesce(`cp_tot`.`amount`,0)) AS `Net`
from (((`vote` join `issues_tot` on((`vote`.`v_code` = `issues_tot`.`v_code`))) join
`office` on((`office`.`oid` = `issues_tot`.`oid`))) left join
`cp_tot` on((`issues_tot`.`v_code` = `cp_tot`.`v_code`)))
But it generates the following output with repeated records:
+------------+----------------+--------------+-------------+--------------+
| Vote | Office | Gross | Cut | Net |
+---------------+-------------+--------------+-------------+--------------+
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 68,000.00 |132,000.00 |
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 50,000.00 | 150,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 68,000.00 | 12,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 50,000.00 | 30,000.00 |
| 001-1-4-21-2202| Weeraketiya | 40,000.00 | - | 40,000.00 |
| 101-1-2-0-1405 | Tissamaharama | 150,000.00 | 75,000.00 | 75,000.00 |
+------------+-----------------+--------------+-------------+--------------+
I can not understand what was going wrong. Can anyone help me?
Firstly, the following query will get what you want:
select
v.vote,
o.office,
it.amount as Gross,
coalesce(ct.amount , 0) as Cut,
it.amount - coalesce(ct.amount, 0) as Net
from issues_tot it
left join cp_tot ct
on it.v_code = ct.v_code
and it.oid = ct.oid
left join vote v
on it.v_code = v.v_code
left join office o
on it.oid = o.oid
order by it.v_code
and SQLFiddle Demo Here, the only issue is that you forget to match oid between issues_tot and cp_tot.
If there is no oid criteria, the match will do like following:
# issues_tot # cp_tot
| v_code | oid | amount | | v_code | oid | amount |
+---------+------+------------+ +--------+-----+-----------+
| 1 | 2 | 200,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 1 | 3 | 80,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 2 | 1 | 40,000.00 | -> no record match
| 3 | 2 | 150,000.00 | -> | 3 | 2 | 75,000.00 |
so 6 records by your query is it.

Get rows that doesn't match on another table

I have this working query that generate data the way i like it to happened but now i want it to add another clause statement that will get rows from tbl_loan_master that was not on the tbl_loanledger.
Example Data:
tbl_borrowers
------------------------------------------
| id | first_name | last_name | deleted |
| 1 | Joe | Smith | 0 |
| 2 | Lily | Mag | 0 |
| 3 | Zen | Green | 0 |
| 4 | Kim | Chan | 0 |
| 5 | Bob | Mac | 1 |
| 6 | Ben | Cork | 0 |
------------------------------------------
tbl_loan_master
----------------------------------------------------------------------
| id | borrowers_id | loan | date_created | due_date | deleted |
| 1 | 4 | 300 | 2016/04/28 | 2017/04/28 | 0 |
| 2 | 1 | 100 | 2016/05/05 | 2017/05/05 | 0 |
| 3 | 2 | 500 | 2016/06/08 | 2017/06/08 | 0 |
| 4 | 1 | 200 | 2016/06/13 | 2017/06/13 | 0 |
| 5 | 3 | 150 | 2016/06/15 | 2017/06/15 | 0 |
| 6 | 6 | 50 | 2016/06/16 | 2017/06/16 | 0 |
----------------------------------------------------------------------
tbl_loanledger
------------------------------------------------------------------------------
| id | borrowers_id | loanmaster_id | payment | balance| date_created | deleted
| 1 | 4 | 1 | 50 | 250 | 2016/05/28 | 0
| 2 | 1 | 2 | 20 | 80 | 2016/05/25 | 0
| 3 | 1 | 2 | 30 | 50 | 2016/06/01 | 0
| 4 | 2 | 3 | 100 | 400 | 2016/06/09 | 0
| 5 | 2 | 3 | 50 | 350 | 2016/06/10 | 0
| 6 | 3 | 4 | 50 | 150 | 2016/06/16 | 0
------------------------------------------------------------------------------
Here is the working query:
$query = "SELECT `tbl_borrowers`.* , `tbl_loanledger`.*, `tbl_loan_master`.*
FROM `tbl_borrowers`
LEFT JOIN `tbl_loanledger`
ON `tbl_borrowers`.id = `tbl_loanledger`.borrower_id
LEFT JOIN `tbl_loan_master`
ON `tbl_loan_master`.id = `tbl_loanledger`.loanmaster_id
WHERE `tbl_borrowers`.deleted = 0 AND `tbl_loanledger`.deleted = 0 AND MONTH ( `tbl_loanledger`.date_created) = MONTH(CURRENT_DATE)
GROUP BY `tbl_loanledger`.borrower_id
ORDER BY `tbl_borrowers`.last_name";
The expected result will output the borrowers with their last transaction on the current month (which is June) in loan ledger and also in loans accounts. Like Ben Cork which is not on the loan ledger, he is on the loan accounts but i want to output him on the result set. The deleted column means if it is 0 it indicates it is active if it is 0 it means it has been deleted.
Expected Result:
|First Name | Last Name | Due Date | Balance |
| Ben | Cork | 2017/06/16 | 50 |
| Joe | Smith | 2017/06/13 | 50 |
| Lily | Mag | 2017/06/08 | 350 |
| Zen | Green | 2017/06/15 | 150 |
Try following;)
select
tb.first_name, tb.last_name, coalesce(tlm.Loan, 0) as Loan, coalesce(t.`Amount Paid`, 0) as `Last Amount Paid`
from tbl_borrowers tb
left join tbl_loan_master tlm
on tb.id = tlm.borrowers_id
left join (
select t1.*
from tbl_loanledger t1
inner join (
select max(id) as id
from tbl_loanledger
group by borrowers_id, loanmaster_id
) t2 on t1.id = t2.id
) t
on tb.id = t.borrowers_id
and tlm.id = t.loanmaster_id
SQLFiddle DEMO HERE

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