Merge multiple row then left join-php mysql - php

I have two tables: invoices and sales. These are simplified version of them:
Invoices:
InvoiceNo | ProductNo | QtyIn
-----------------------------------
F01 | 00001 | 20
F01 | 00002 | 50
F01 | 00003 | 15
F02 | 00002 | 10
Sales:
Date | ProductNo | QtyOut
---------------------------------
3/2/17 | 00002 | 12
3/3/17 | 00002 | 8
3/4/17 | 00003 | 10
What I'm trying to do is to make a stock summary table, which looks like this:
ProductNo | QtyIn | QtyOut | Stock
-------------------------------------------
00001 | 20 | 0 | 20
00002 | 60 | 20 | 40
00003 | 15 | 10 | 5
To make that stock table, as far as I can think is:
Make another database for invoice where same product will be merge
and it's quantity will be sum up.
Make something like the first one for sales.
Then make a join table for both of them.
By this way, I will end up having 5 tables. Is there any simpler way to do this? Thanks.

If you apply a filer on Invoices and Sales (e.g. for a date range) either filtered result could have products not referenced in the other. Hence a single outer join does not cover all possible conditions. As there is no "full outer join" in MySQL a simple method to overcome this is to union all source rows then group that:
select ProductNo, sum(QtyIn) QtyIn, sum(QtyOut) QtyOut, sum(QtyIn) - sum(QtyOut) Stock
from (
select ProductNo, QtyIn, 0 as QtyOut
from invoices
# where datecol >= `2017-01-01`
union all
select ProductNo, 0 as QtyIn, QtyOut
from Sales
# where datecol >= `2017-01-01`
) u
group by ProductNo

Mysql Query is
Select a.ProductNo , a.QtyIn, b.QtyOut, a.QtyIn-b.QtyOut as "Stock" from Invoices a join Sales b on a.productNo=q.productNo

Related

mySQL rank order by sum of values in table that have it name in in another table

I have two mySQL database table, I'm using one to store to product information and the other to store the sales information of product sold, where it receive my product_id as the product it sold
product Table example
product_id | prod_name |
------------------------
1 | toyota |
2 | lexus |
3 | wagon |
sale Table example
sale_id | prod_id | qty
------------------------
1 | 1 | 5
2 | 1 | 1
3 | 3 | 2
4 | 1 | 4
5 | 2 | 5
6 | 2 | 1
Now i want the mysqli datebase to tabulate the sum of the most sold product name using php and html table
you can use this query
SELECT
product.product_id,
product.prod_name,
sum(qty) as total
FROM sale
INNER JOIN product
ON
sale.prod_id=product.product_id
GROUP BY
product.product_id
ORDER BY
total DESC
this fiddle if you want to see the results
and you just need to echo the column name if you want to show it to your table on php

MySQL: Joining a table to itself, eliminating duplicate rows

I have a query that connects a table to itself. The results contain duplicate rows (sort of). The objective of this query is to produce a list of products most frequently purchased together. Consider this query:
SELECT o1.ITEM
,o2.ITEM as ITEM2
,o3.ITEM AS ITEM3
,count(DISTINCT o1.ORDERNUM) as oCount
FROM orders o1
INNER JOIN orders o2 ON o2.ORDERNUM = o1.ORDERNUM AND o2.ITEM != o1.ITEM
LEFT OUTER JOIN orders o3 ON o3.ORDERNUM = o1.ORDERNUM AND o3.ITEM != o2.ITEM AND o3.ITEM != o1.ITEM
GROUP BY o1.ITEM, o2.ITEM, o3.ITEM
ORDER BY oCount DESC
And the first 12 results:
+-------------+-------------+-------------+--------+
| ITEM | ITEM2 | ITEM3 | oCount |
+-------------+-------------+-------------+--------+
| 02B13.04.GP | 77A04.10 | 45A04.04.GP | 54 |
| 02B13.04.GP | 45A04.04.GP | 77A04.10 | 54 |
| 77A04.10 | 45A04.04.GP | 02B13.04.GP | 54 |
| 45A04.04.GP | 02B13.04.GP | 77A04.10 | 54 |
| 77A04.10 | 02B13.04.GP | 45A04.04.GP | 54 |
| 45A04.04.GP | 77A04.10 | 02B13.04.GP | 54 |
| 57B01.01.GP | 57B01.11.GP | 57B01.10.GP | 12 |
| 57B01.10.GP | 57B01.11.GP | 57B01.01.GP | 12 |
| 57B01.01.GP | 57B01.10.GP | 57B01.11.GP | 12 |
| 57B01.10.GP | 57B01.01.GP | 57B01.11.GP | 12 |
| 57B01.11.GP | 57B01.10.GP | 57B01.01.GP | 12 |
| 57B01.11.GP | 57B01.01.GP | 57B01.10.GP | 12 |
Note that the first 6 results are the same connections, in a different order. The second 6 results have the same issue (and this continues throughout the results). My goal is to have a single record for each item group, not a single row for each combination of each item group.
How can I avoid these repeated results?
Also any advice on a more efficient approach to this query would be welcome (I'd like to add an additional join, but with 1,000,000 orders the resource requirements are getting out of hand).
================================================
EDIT: To answer Darshan's questions
Can you share the table structure:
The table contains the lines for all the orders. If an order contains multiple products, there will be a line for each product (multiple lines for a given order). The only columns of concern in this query are:
ORDERNUM CHAR : Order Number
ITEM CHAR : SKU for the item
QTY INT : Quantity purchased
ORDDATE DATETIME : Order Date
Results returned: All I need is what I listed in the result sample above. The objective is to get a list of the products that are purchased together the most often.
What you want to do is to eliminate duplicated rows regardless of the position; one trick, since you always have all the combinations of items is to filter the results according to a predicate that says item1 < item2 < item3
Here is a possible solution:
SELECT a.item, b.item, c.item, count(*)
from `orders` a left join orders b
on a.ordernum = b.ordernum and a.item <> b.item
left join orders c on a.ordernum = c.ordernum
and a.item <> c.item and b.item <> c.item
where a.item < b.item and b.item < c.item
group by a.item, b.item, c.item
order by count(*) desc

Select distinct and random rows from one table that match a value from another table

This topic has been much discussed but I was unable to find a solution that I can modify and make it work for my case. So maybe a more advanced expert will be able to help out.
I have a table called keywords which contains about 3000 rows with distinct keywords. Against each keyword there is a matching product_id, which are NOT unique, i.e. some of them are repeated. Table looks something like this:
+---------+------------+
| keyword | product_id |
+---------+------------+
| apple1 | 15 |
| apple2 | 15 |
| pear | 205 |
| cherry | 307 |
| melon | 5023 |
+---------+------------+
I have a second table called inventory that contains about 500K of products each with it's own product ID and other product data.
Now I need to get one random product row from inventory table that matches each product_id from keywords table and insert those rows into another table.
Resulting table should be something like this:
+---------+------------+---------+---------+---------+
| keyword | product_id | product | data1 | data2 |
+---------+------------+---------+---------+---------+
| apple1 | 15 | app5 | d1 | d2 |
| apple2 | 15 | app1 | d1 | d2 |
| pear | 205 | pear53 | d1 | d2 |
| cherry | 307 | cher74 | d1 | d2 |
| melon | 5023 | melo2 | d1 | d2 |
+---------+------------+---------+---------+---------+
This is my query at the moment and the problem is how to get a random product from inventory that matches a product_id:
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords LEFT OUTER JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND();
If you want it to only return rows when there is a match between the tables, then you want a regular (i.e. inner) join not a left outer join. You can also add the word distinct.
SELECT DISTINCT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND();
And if you only want 1 row returned, add limit 1 at the end.
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND() LIMIT 1;
Is this what you want?
SELECT *
FROM (
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND()
) tmp
GROUP BY tmp.keyword;
I also test it at http://sqlfiddle.com/#!2/e559a9/2/0. Just run some times, the result will be randomize.

MySQL - Combine tables and order by max date

I have two mysql tables which I've simplified below. I would like to create a query which would pull the data from both tables and order by the most recent date. So if there's an entry (or entries) in the notes table it would look for the most recent notes_date for that cid, and if there's no entry it would use the contact_date for that cid.
contacts
+-----+--------+---------------------+
| cid | name | contact_date |
+-----+------------------------------+
| 1 | george | 2014-03-03 12:24:48 |
| 2 | john | 2014-02-28 15:39:20 |
| 3 | paul | 2014-02-14 10:13:58 |
| 4 | ringo | 2014-02-06 07:13:17 |
+-----+--------+---------------------+
notes
+-----+-----+---------------------+
| nid | cid | notes_date |
+-----+---------------------------+
| 1 | 1 | 2014-03-06 15:43:55 |
| 2 | 1 | 2014-03-14 20:14:12 |
| 3 | 4 | 2014-03-20 22:10:14 |
+-----+-----+---------------------+
This is the result I'd like to get from the query
4 ringo 2014-03-20 22:10:14
1 george 2014-03-14 20:14:12
2 john 2014-02-28 15:39:20
3 paul 2014-02-14 10:13:58
Any help would be much appreciated
This has a few parts to it. One is getting the most recent date for notes. Another is combining this with the contacts data and then choosing the right date.
The following approach uses an aggregation subquery and join to do the calculation:
select c.cid, c.name, coalesce(n.notes_date, c.contact_date) as thedate
from contacts c left outer join
(select n.cid, max(notes_date) as notes_date
from notes
group by n.cid
) n
on c.cid = n.cid
You should use join. You can have query like-
select cont.cid, cont.name, nots.notes_date from contacts cont inner join notes nots on cont.cid=nots.cid order by nots.notes_date

sum two different table and the subtract its total

i have this problem with me on how to sum total value from two different table and then after getting its total i want to subtract it. for example i have table "rsales" and "sales" and i have these ff vlue below.
data from "rsales"
id | total | pcode |
1 | 100 | 2143 |
2 | 100 | 2143 |
3 | 50 | 2222 |
4 | 50 | 2222 |
data from "sales"
id | total | pcode |
7 | 100 | 2143 |
8 | 50 | 2222 |
my problem is this. i want to sum all "total" values from sales and sum "total"value from rsales group by pcode.and then after getting its sum i want to subtract it. my page must be something like this.
total pcode
| 100 | 2143 |
| 50 | 2222 |
i have this ff code but it doesnt wor for me
sql "select sum(rsales.total)- sum(sales.total) as t1 where pcode = rsales.pcode"
Use:
SELECT
SUM(r.total)-(
SELECT SUM(s.total)
FROM sales AS s WHERE r.pcode=s.pcode
) as total,
r.pcode
FROM rsales AS r
GROUP BY r.pcode;
Output:
+--+--+--+--+--+-
| total | pcode |
+--+--+--+--+--+-
| 100 | 2143 |
| 50 | 2222 |
+--+--+--+--+--+-
2 rows in set
Have you tried something like this?
SELECT
SUM(L.total) as lTotal, SUM(R.total) as rTotal
FROM
sales L
INNER JOIN rsales R
ON
R.pcode = L.pcode
GROUP BY L.pcode
If you get expected values from both tables you can easily add Additions and Subtruction in FROM clause.
There's no joins needed to do this. This solution works if some pcodes are only in one table:
select SUM(total), pcode from (
select sum(total) as total, pcode from rsales group by pcode
union all
select SUM(-total) as total, pcode from sales group by pcode) salesTables
group by pcode

Categories