SQL Complexed Join - php

I want to list a Purchase Record for a customer by the following tables.
Table: Invoice
----------------------
invID | cusID | total
----------------------
1 | 1 | 10.5
Table: Invoice Item
--------------------
invID | prodID
---------------
1 | 1
1 | 3
Now I want to output as one row Like this: (or in PHP Fetched Row Table)
invID | cusID | prodID | total
-------------------------------
1 | 1 | 1, 3 | 10.5
What have I tried:
SELECT i.*, ii.prodID FROM invoice i, invoiceitem ii WHERE cusID = '1' AND i.invID = ii.invID
Result:
invID | cusID | prodID | total
-------------------------------
1 | 1 | 1 | 10.5
1 | 1 | 3 | 10.5

I think this will work for you. Haven't tested it so there might be a minor typo somewhere, but the concept should work.
SELECT i.invID, i.cusID, GROUP_CONCAT(ii.prodID) `prodID`, i.total
FROM invoice i
INNER JOIN invoiceitem ii ON i.invID = ii.invID
GROUP BY i.invID

You are just missing a GROUP_CONCAT over the prodIDs. You should also use ANSI INNER JOIN syntax, in preference to joining in the WHERE clause. Although MySql doesn't complain, it is also good practice to include all non-aggregated select fields in the GROUP BY, for compliance with other RDBMS's
SELECT i.invID, i.cusID, GROUP_CONCAT(ii.prodID) as prodID, i.total
FROM invoice i INNER JOIN invoiceitem ii ON i.invID = ii.invID
WHERE cusID = '1'
GROUP BY i.invID, i.cusID, i.total;

Related

Sum of column is not working in join table PHP

I am trying to calculate the req_qty and in_qty from table1 and table2.
I am trying to fetch the joined 3 tables data SUM(req_qty), SUM(in_qty). Issue come if req.qty not save in table2 it will not works. I am left joining the table by this sku's ids
I made here a very simple table for calculating the sum of the column. generally, the sum of the column is multiplying the total rows.
Please don't close the post and guild for other thread. for my doubt clear i made here a table which I can understand. please help.
table1
ID | sku_1 | req_qty | trans_id
----------------------------------
1 | 123 | 150 | 12345
2 | 142 | 200 | 256314
3 | 123 | 100 | 896523
table2
ID | sku_2 | in_qty | trans_key
-----------------------------------
1 | 142 | 50 | 002563
table3
ID | sku_code | sku_name
--------------------------
1 | 142 | ABC
2 | 123 | XYZ
Expected Output
ID | sku | sku_name | reqQty | inQty
------------------------------------
1 | 123 | XYZ | 250 | 0
2 | 142 | ABC | 200 | 50
Edit to select data when table1 and table2 are empty
SELECT table1.id, table3.sku_code as sku, table3.sku_name,
sum(table1.req_qty) as reqQty, sum(table2.in_qty) as inQty
FROM table3
LEFT JOIN table1 on table3.sku_code = table1.sku_1
LEFT JOIN table2 on table3.sku_code = table2.sku_2
GROUP BY table1.id, table3.sku_code, table3.sku_name
Explanation
You can see an explanation on how left join works here https://www.w3schools.com/sql/sql_join_left.asp#:~:text=The%20LEFT%20JOIN%20keyword%20returns,if%20there%20is%20no%20match.
But to explain this query quickly, we will select all data from table3, left join will find all records from left table (here table3) and mathcing records from right tables (here table2 and table 1).

Mysql joining two tables and counting total records based on primary key

I have two tables vendor and medicines on mysql database now i need to count total medicines transacted based on vendor ID with a condition status is equal to paid, in a single query and show it to my users
My vendor table looks like this
| ID | vendor_name |
+----+------------------+
| 1 | Marakel Medicine |
| 2 | Ignacio Pharmacy |
| 3 | Rico Medicines |
| 4 | Marco Pharmacy |
+----+------------------+
My Medicines table looks like this.
| ID | vendor_id | medicine_name | Status |
+----+-----------+----------------+---------+
| 1 | 1 | paracetamol #1 | paid |
| 2 | 1 | paracetamol #1 | paid |
| 3 | 2 | paracetamol #1 | pending |
| 4 | 2 | paracetamol #1 | paid |
| 5 | 4 | paracetamol #1 | paid |
+----+-----------+----------------+---------+
My desire output would be like this
+----+------------------+-----------+
| ID | vendor_name | Total Med |
+----+------------------+-----------+
| 1 | Marakel Medicine | 2 |
| 2 | Ignacio Pharmacy | 1 |
| 3 | Rico Medicines | 0 |
| 4 | Marco Pharmacy | 1 |
+----+------------------+-----------+
So far my code is below i was able to output per vendor i just don't have an idea how to count them based on there status, any suggestion would be great!
SELECT * FROM vendors LEFT JOIN medicine ON vendor.ID = medicines.vendor_id
Join Operation on tables based on status[paid or pending] & vendor name :
Proposed Query :
SELECT vendor.ID, vendor.vendor_name,
COUNT((CASE WHEN [status] <> 'pending' THEN 1 END)) AS 'Total Med'
FROM medicines RIGHT OUTER JOIN
vendor ON medicines.vendor_id = vendor.ID
GROUP BY vendor.vendor_name, vendor.ID
Note:
This query has been worked out in MSSQL, you can refer the logic and try for MySQL.
Corresponding MySQL Syntax:
SELECT vendor.ID, vendor.vendor_name,
COUNT((CASE WHEN status <> 'pending' THEN 1 END)) AS 'Total Med'
FROM medicines
RIGHT OUTER JOIN vendor ON
medicines.vendor_id = vendor.ID GROUP BY vendor.vendor_name, vendor.ID
Use GROUP BY and COUNT
SELECT
v.ID,
v.vendor_name,
COUNT(m.vendor_id) AS 'Total Med'
FROM
vendors v
LEFT JOIN medicine m ON v.ID = m.vendor_id
GROUP BY
v.ID
MYSQL version of #tharif's MSSQL solution.
SELECT
v.ID,
v.vendor_name,
COUNT((CASE WHEN m.`status` <> 'pending' THEN 1 END)) AS 'Total Med'
FROM
vendor v
LEFT JOIN medicines m ON v.ID = m.vendor_id
GROUP BY v.ID
It is a good idea to read on group by and count if you are new to these.
you should try this
SELECT v.ID,v.vendor_name,COUNT(m.ID) as `Total`
FROM vendor v LEFT JOIN medicines m ON v.ID=m.vendor_id
GROUP BY m.ID
Use Group By its an sql function and also use count its also an sql built in function..some similar shown below.
SELECT vendors.id,vendors.vendor_name,COUNT(medicine.vendor_id) AS 'Total Transaction'
FROM vendors LEFT JOIN medicine ON vendors.id = medicine.vendor_id
GROUP BY vendors.id

Sort products prices from multiple tables in MySQL

What is the way to sort a MYSQL result from multiple tables?
I have two tables. The first:
"store_products" table:
+----+-----------+
| id | name |
+----+-----------+
| 1 | Product 1 |
| 2 | Product 2 |
| 3 | Product 3 |
+----+-----------+
Here i placed product names. Other table contains prices for different product variants:
"store_products_variants" table:
+-----+------------+-------------+-------------+
| id | product_id | price_sale | ordering |
+-----+------------+-------------+-------------+
| 5 | 1 | 06.00 | 2 |
| 6 | 1 | 32.00 | 3 |
| 11 | 1 | 56.00 | 1 |
| 14 | 2 | 09.00 | 1 |
| 44 | 3 | 15.00 | 1 |
+-----+------------+-------------+-------------+
I need to create a sort on price (lowest and highest), that uses only first variant - ordered by column "ordering" from "store_products_variants" table.
From example above, the results should be:
+---+------------+---------------+
| 1 | Product 2 | (price 09.00) |
| 3 | Product 3 | (price 15.00) |
| 2 | Product 1 | (price 56.00) |
+---+------------+---------------+
Is this possible in MySQL?
Use the ordering column to join the correct variant onto the product.
This would be the query if the correct ordering value was always the 1.
SELECT
products.name,
variants.price_sale
FROM store_products AS products
INNER JOIN store_products_variants AS variants
ON variants.product_id = products.id
AND variants.ordering = 1
ORDER BY variants.price_sale ASC
This query will first look for the lowest ordering value of a product. Then use it to join the price on your result:
SELECT
products.name,
variants.price_sale
FROM
store_products AS products
INNER JOIN (
SELECT
product_id,
MIN(ordering) AS ordering
FROM
store_products_variants
GROUP BY
product_id
) AS variantOrdering
ON variantOrdering.product_id = products.id
INNER JOIN store_products_variants AS variants
ON variants.product_id = variantOrdering.product_id
AND variants.ordering = variantOrdering.ordering
ORDER BY
variants.price_sale ASC
select t.* from(
select t1.[id], t1.[name],
'(price ' + cast(max(t2.[price_sale]) as varchar(50)) + ')' as [price]
from [#store_products] t1
left join [#store_products_variants] t2
on t1.[id] = t2.[]product_id
group by t1.[id], t1.[name]
)t
Order by len(t.[price]), t.[price];
Yes this is possible. Try to use the JOIN command, and JOIN on the ID of each table.
Hello this is possible please use this query
SELECT p.id,p.name,spv.price_sale
from products p
INNER JOIN store_products_variants spv ON spv.product_id = p.id
where spv.ordering = 1
group by p.id
order by spv.price_sale asc
i think it gives the result what you want

subtract from two different table

i have 3 tables tables "productlist, sales, return" so let say for example i have 3 sales and 2 return as given below.
this is the ff data from productlist
id | pcode | pname | pdesc |
1 | 222 | 33uf | 10v |
this is the ff data from sales
id | pcode | total | profit
1 | 222 | 200 | 10
2 | 222 | 100 | 10
3 | 222 | 200 | 10
this is the ff data from return
id | pcode | total | lose
3 | 222 | 200 | 10
4 | 222 | 100 | 10
My problem is this. I want to select data from productlist and sum the "total" and "profit" Value from sales and sum the "total" and "lose" value from return. And then subtracting my two table to get the result. The expected result must be something like this.
id | pcode | pname | pdesc | total | profit |
1 | 222 | 33uf | 10v | 200 | 10 |
I have this ff code but I can't subtract "total" from sales to "total" from return and "profit" from sales and "lose" from return.
$result = mysql_query("SELECT
productlist.*,
SUM(sales.total)-SUM(return.total) as total,
SUM(sales.profit)-SUM(return.lose) as profit
FROM productlist
LEFT JOIN sales ON sales.pcode = productlist.pcode AND return ON return.pcode = productlist.pcode
GROUP BY pcode
ORDER BY total ASC");
You seem to be trying to join two tables with AND, that's not quite right ;)
Try this:
...
LEFT JOIN `sales` USING (`pcode`)
LEFT JOIN `return` USING (`pcode`)
...
I'm not completely certain this'll work, it may complain of column `pcode` is ambiguous. If this happens, try this instead:
...
LEFT JOIN `sales` ON `sales`.`pcode` = `productlist`.`pcode`
LEFT JOIN `return` ON `return`.`pcode` = `productlist`.`pcode`
...
The structure of your query is not going to return the right results. Not matter how you fix the syntax, you will still be getting a cartesian product between the sales and returns for a given product.
One fix is to do aggregations before the joins:
SELECT pl.*,
(coalesce(s.total, 0) - coalesce(r.total, 0)) as total,
(coalesce(s.profit, 0) - coalesce(r.lose, 0)) as profit
FROM productlist pl left join
(select pcode, sum(total) as total, sum(profit) as profit
from sales
group by pcode
)
on s.pcode = pl.pcode left join
(select pcode, sum(total) as total
from return
group by pcode
) r
on r.pcode = pl.pcode
ORDER BY total ASC;

mysql select from where different

I need to select a list of entries, but need to skip those that have matching fields in 2 different tables.
Here's my DB structure
orders:
| orders_id | customers_id |
| 100 | 01 |
| 101 | 20 |
| 102 | 32 |
| 103 | 48 |
| 104 | 99 |
customers (for reference only):
| firstname | lastname | customers_id |
| John | Doe | 20 |
| Fred | Flinty | 22 |
| Mark | Smith | 32 |
testimonials:
| customers_id | testimonial |
| 20 | aaa |
| 32 | bbb |
| 38 | ccc |
| 49 | ddd |
| 55 | eee |
So, I need to select all customers who are in my Orders table, but need to skip them if they are in my Testimonials table. In the example shown above, I would need to select only customers 01, 48 and 99 because they don't exist in Testimonials table.
This is what I tried, but am obviously missing something:
SELECT c.firstname, c.lastname, c.customers_id, o.orders_id,
o.customers_id, s.date_added as status_date
FROM (orders o, testimonials t )
JOIN customers c
ON c.customers_id = o.customers_id
JOIN status_history s
ON s.orders_id = o.orders_id
and s.orders_status_id = o.orders_status
and o.customers_id != t.customer_id
order by o.orders_id ASC;
Can somebody please tell me what I'm doing wrong and how to skip customers that are found in both tables (orders and testimonials)?
I feel I'm on the right track because, if I change the and o.customers_id != t.customer_id to and o.customers_id = t.customer_id I get only the customers that are in both tables (in this case, 20 and 32).
You can LEFT JOIN on this.
The reason for using LEFT JOIN is because it will show all records from the table defined on lefthand side whether it has a matching record or not on the table define on the righthand side. When table Orders is joined with table testimonials, all the records that have no match will have a value of null for the columns in the testimonials table and that's the one you are looking for. To filter out, we only need to get records with NULL value by checking the column with IS NULL.
SELECT a.*, b.*
FROM orders a
LEFT JOIN testimonials c
ON a.customers_ID = c.customers_ID
LEFT JOIN customers b
ON a.customers_ID = b.customers_ID
WHERE c.customers_ID IS NULL
SQLFiddle Demo
SQLFiddle Demo (added some info on the mismatched customer)
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Adding up INDEX.
If on the real database the Orders table as well as Testimonials are always dependent on Customers table, then a FOREIGN KEY constraint should be enforce to preserve referential integrity.
Here's how:
ALTER TABLE Orders ADD CONSTRAINT tb_fk1
FOREIGN KEY (Customers_ID) REFERENCES Customers(Customers_ID);
ALTER TABLE Testimonials ADD CONSTRAINT tb_fk2
FOREIGN KEY (Customers_ID) REFERENCES Customers(Customers_ID);
This is easy way.
select c.* from order as o
join customers as c on o.customers_id = c.customers_id
where o.customers_id not in(select customers_id from testimonials)

Categories