Exclude result from MySQL query in JOIN - php

I have multiple tables with orders and deliveries and I want to get only open orders (only those orders that do not have records in delivery table).
So, my tables look like:
Orders table (sh_comenzi):
id partner
1 Partner X
2 Partner Y
3 Partner Z
4 Partner Q
Order lines table (sh_comenzi_pos) where idc is the id of sh_comenzi table
id idc cPos quantity
1 1 1 5
2 1 2 10
3 1 3 20
4 2 1 10
5 2 2 15
6 3 1 10
7 3 2 5
8 3 3 8
9 4 1 15
The deliveries items table is (sh_delivery_items)
id idc cPos
1 1 1
2 1 3
3 2 2
4 3 1
5 3 2
6 3 3
The desired result should give me an output of open orders just like this:
id partner
1 Partner X
2 Partner Y
4 Partner Q
The result doesn't have to keep track o quantities, just on lines level. If one line from orders exists in sh_delivery_items then that line is closed.
I tried something like this:
SELECT DISTINCT sh_comenzi.id, partner FROM sh_comenzi
LEFT JOIN sh_comenzi_pos ON sh_comenzi.id = sh_comenzi_pos.idc
LEFT JOIN sh_delivery_items ON (sh_comenzi_pos.idc = sh_delivery_items.idc AND sh_comenzi_pos.cPos = sh_delivery_items.cPos)
WHERE sh_comenzi.id IS NOT NULL
ORDER BY sh_comenzi.id DESC
Could someone help me?

This is the query you need:
SELECT DISTINCT c.*
FROM sh_comenzi c
INNER JOIN sh_comenzi_pos p
ON c.id = p.idc
LEFT JOIN sh_delivery_items di # 'di' from 'delivery items'
ON p.idc = di.idc AND p.cPos = di.cPos
WHERE di.id IS NULL # keep only not-delivered items
How it works
It combines all the orders (table sh_comenzi) with their line items (table sh_comenzi_pos). The INNER JOIN will leave out the empty orders (if any); if you need them then use LEFT JOIN instead.
Next, each row (order, line item) is combined with the delivery information (table sh_delivery_items) using the pair of columns (idc, cPos). The LEFT JOIN ensures all the rows from the left side table (or result set) appear in the final result set; if a row from the right side table cannot be found to match the row from the left, a row full of NULLs is used instead. This happens for the line items that were not delivered yet (there is no record for them in sh_delivery_items).
Then, the WHERE clause keeps only the rows having NULLs in the di table (sh_delivery_items), i.e. the line items that were not delivered, together with the orders that own them.
Finally, SELECT DISTINCT c.* selects only the columns from the orders table (sh_comenzi) and DISTINCT ensures each order appear only once. Otherwise, each order appears once for each of its line items that was not delivered.
Complete the query yourself with the desired ORDER BY clause.

Related

How to get data from different tables in MySQL database and display in a table with php

I have read many topics but none have given me exactly what i need
I have 3 tables
products
id
product_name
1
Heineken
2
Budweiser
transaction
id
user_id
date
amount
32
4
01/23/2023
10000
45
2
01/23/2023
20000
57
4
01/23/2023
5000
transaction_details
id
transaction_id
product_id
1
32
1
2
32
2
3
45
2
4
45
1
5
57
1
Now how can i achieve this
SELECT FROM transaction WHERE user_id = 4 then use the results to SELECT FROM transaction_details and display it in a table using a single sql query
And when displaying the results from transaction_details i want to use product_name
This is the result i want
transaction_id
products_id and name
32
1. Heineken
32
2. Budweiser
57
1. Heineken
I have tried to select from transaction table where id is equal to 4 and i got two results, i don't know what to do next
Using Mysqli Join Query with select concat option in in your select query
Please Using This Way
select tran.id,CONCAT(pro.id,'.',pro.product_name) as products_id_and_name from transaction as tran join transaction_details as trand on tran.id = trand.transaction_id JOIN products as pro on pro.id = trand.product_id WHERE tran.user_id = 4;

Mysql join two table and set group in all tables

Hello I have two table in my database, customers and shops.
I want to get all customers and clarify that a customer is a debtor or not.
For this job I want to create a mysql query that get the customers and join the shop table.
I want to set condition for if shops.price_status column = 1 come and sum price value in shops table.
Otherwise the value of those row for price column in shop table equal to 0.
My shop table structure with some example data
id customer_id product_id price price_status
1 81 12 300 1
2 81 12 100 0
3 81 15 200 1
4 90 10 600 0
5 90 15 50 1
6 63 16 10 0
And my customer table (You should know some customers don't shop any product by I want to see them)
id name
63. Eva
64. Nva
81. Ali
82. Bill
90. Mosh
An I want to get this result
Eva. 0. // Because price status = 0
Nva. 0.
Ali. 500 // because have two row that prices status = 1
Bill. 0.
Mosh. 50. // Because have one row with price status = 1
this can do with [MySQL if][1]
SELECT
c.`name`,sum(if(s.price_status=1,s.price,0)) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;
if you accept null value in price you can use
SELECT
c.`name`,sum(s.price_status*s.price) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;

Mysql join two tables with sum of quantity

Q : I am trouble to do following task in mysql query.
Task is get all products (If product is duplicate than sum of it's qty) and deduct wastage stock (If wastage product is duplicate than sum of it's qty).
I have two tables like,
1) manage_stock
2) manage_wastage
manage_stock
=> This table has p_id(Product ID) and many rows with product duplication's.
p_id p_name p_qty
1 Pro-1 10
2 Pro-2 15
3 Pro-3 8
1 Pro-1 15
manage_wastage
=> This table has p_id(Product ID) of manage_stock table. It is also many rows with product duplication's.
p_id w_qty
1 2
1 4
3 5
Desired Output
p_id p_name p_qty w_qty final_qty
1 Pro-1 20 6 14
2 Pro-2 15 0 15
3 Pro-3 8 5 3
Thank you very much.
You just have to compute the difference between the stock quantity and the wastage
SELECT s.p_id, s.p_name, SUM(p_qty), SUM(w_qty), SUM(p_qty) - SUM(w_qty) as final_qty
FROM manage_stock s
LEFT OUTER JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_id, s.p_name
try this one
SELECT s.p_id, s.p_name, SUM(p_qty),SUM(ifnull(w_qty, 0)),SUM(p_qty - ifnull(w_qty, 0)) as total
FROM manage_stock s
left outer JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_name
its work
SELECT ms.p_id ,GROUP_CONCAT(ms.p_name)p_name ,SUM(ms.p_qty) p_qty ,SUM(mw.w_qty) w_qty,SUM(ms.p_qty)-SUM(mw.w_qty) final_qty FROM manage_stock ms
INNER JOIN manage_wastage mw on ms.p_id =mw.p_id
GROUP BY ms.p_id
Try above code.
As p_name always unique with p_id GROUP_CONCAT() only returns single name.

MySQL Group By Product Id BUT NOT Product that has a Serial Number

Can someone help me how to make an efficient mysql query for this?
I need to make a query to get the sum quantity of all ordered items.
combined with.
I need to make a query to get the sum quantity of all received items.
Please note that some products have serial numbers when received and some don't in my 'received_po_details' table. That's where I'm having problem with since the sum of received gets doubled because of the serial numbers.
Table: received_po_details
i_rpoh_id i_p_id i_quantity_received s_product_serial
1 1 100
1 2 100
1 3 50
1 4 25
1 7 100
1 8 50
1 6 1 XYZ1
1 6 1 XYZ2
1 5 1 ABC1
1 5 1 ABC2
Right now I have these 2 separate sql that I need to combine.
I don't want to use Union statement for this if possible...
-- to get the Total Quantity Ordered
SELECT
products.i_id AS 'ID',
products.s_name AS 'Name',
COALESCE(SUM(purchase_order_details.i_quantity_ordered),0) AS 'Total Quantity Ordered'
FROM
products
LEFT JOIN
purchase_order_details
ON
products.i_id = purchase_order_details.i_p_id
GROUP BY
products.i_id
-- to get the Total Quantity Received
SELECT
products.i_id AS 'ID',
products.s_name AS 'Name',
COALESCE(SUM(received_po_details.i_quantity_received),0) AS 'Total Quantity Received'
FROM
products
LEFT JOIN
received_po_details
ON
products.i_id = received_po_details.i_p_id
GROUP BY
products.i_id
You can combine these queries by creating a derived table or each type of sum (in the query below they're named t1 and t2) and left joining the derived tables to the main product table.
SELECT
p.i_id AS 'ID',
p.s_name AS 'Name',
COALESCE(t1.total,0) 'Total Quantity Ordered',
COALESCE(t2.total,0) 'Total Quantity Received'
FROM products p
LEFT JOIN (
SELECT
pod.i_p_id,
SUM(pod.i_quantity_ordered) total
FROM purchase_order_details pod
GROUP BY pod.i_p_id
) t1 ON t1.i_p_id = p.i_id
LEFT JOIN (
SELECT
rpd.i_p_id,
SUM(rpd.i_quantity_received) total
FROM received_po_details rpd
GROUP BY rpd.i_p_id
) t2 ON p.i_id = t2.i_p_id

Help with limiting a joined mysql database query

I have written a query which returns all records with some many-to-many joins correctly for the entire set or an individual article using WHERE a.id = ?
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id
LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id
LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id
LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
BUT!
I've hit a brick wall trying to work out how to limit the articles to a specific number of IDs, for working with pagination.
I'm ideally trying to use as simple and clear SQL statements as possible because I'm using the codeigniter framework with their active record class.
http://codeigniter.com/user_guide/database/active_record.html
Would really appreciate some help as I don't want to revert to using multiple queries for this as I've tried to reduce it down to a single query for database efficiency.
Have search around and tried some alternatives but nothing seems to work. Many thanks!
For example the results I return are like this
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
2 test 2 2 1 1
2 test 2 1 2 1
2 test 2 1 1 2
2 test 2 5 1 1
2 test 2 8 1 1
2 test 2 1 4 1
2 test 2 1 4 2
I need the results like this so that I can create sub-arrays in the php like this:
$articles = $query->result_array();
$output = array();
foreach ($articles as $article) {
// set up article details
$article_id = $article['id'];
// add article details
$output[$article_id]['article_id'] = $article_id;
$output[$article_id]['date_added'] = $article['date_added'];
$output[$article_id]['title'] = $article['title'];
$output[$article_id]['content'] = $article['content'];
// set up people details and add people array with details if exists
if (isset($article['person_id'])) {
$person_id = $article['person_id'];
$output[$article_id]['people'][$person_id]['person_id'] = $person_id;
$output[$article_id]['people'][$person_id]['lastname'] = $article['lastname'];
$output[$article_id]['people'][$person_id]['firstname'] = $article['firstname'];
}
// set up organizations details and add organizations array with details if exists
if (isset($article['organization_id'])) {
$organization_id = $article['organization_id'];
$output[$article_id]['organizations'][$organization_id]['organization_id'] = $organization_id;
$output[$article_id]['organizations'][$organization_id]['organization_name'] = $article['organization_name'];
}
// set up categories details and add categories array with details if exists
if (isset($article['category_id'])) {
$category_id = $article['category_id'];
$output[$article_id]['categories'][$category_id]['category_id'] = $category_id;
$output[$article_id]['categories'][$category_id]['category_name'] = $article['category_name'];
}
}
But if I just use LIMIT (with offset etc) 1
the results I get are
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
instead of
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
which is my desired result.
OK, so finally I worked out how it is possible.
Thought i'd include it here in case anyone else has the same problem.
Changing this line
FROM articles AS a
to this
FROM (SELECT * FROM articles LIMIT 5,3) AS a
does what I wanted.
So, why don't you use OFFSET 0,10 and LIMIT *number_of_results* in the SQL Query? (if I understood the question)
Specific number of IDs... WHERE ID IN (2,4,6,8)... ?
Are you using codeigniter's pagination?
http://codeigniter.com/user_guide/libraries/pagination.html
You can easily limit the number of records that are being returned using the MySQL LIMIT clause. This can be achieved like the following with your sample query.
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
LIMIT 10
Where 10 is the number of records you wish to display. The MySQL LIMIT clause allows you to specify a limit of the number of records and an initial offset. Like so:
LIMIT <offset>,<limit>
In your case <offset> would be the current page * the number of records on a page. <limit> would be the number of records you would like to display per page.

Categories