Sum of column is not working in join table PHP - 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).

Related

MySQL SUM of multiple rows from multiple table

I am trying to get the sum of multiple rows from 2 different tables, but somehow the result returns multiple rows.
I need to get the SUM of quotation_item_amount (group by quotation_id) and invoice_item_amount (group by invoice_id) and if I query unpaid quotation, I need to get WHERE SUM(invoice) < SUM(quotation)
So here's my sample table
table client_project_id
+-------------------+-----------+----------------------+
| client_project_id | client_id | client_project_title |
+-------------------+-----------+----------------------+
| 23 | 5 | Project 1 |
| 17 | 9 | Project 2 |
| 54 | 7 | Project 3 |
+-------------------+-----------+----------------------+
table quotation
+--------------+-------------------+------------------+
| quotation_id | client_project_id | quotation_number |
+--------------+-------------------+------------------+
| 1 | 23 | Q/01/2020/001 |
| 2 | 17 | Q/01/2020/002 |
| 3 | 54 | Q/01/2020/003 |
+--------------+-------------------+------------------+
table quotation_item
+-------------------+--------------+-----------------------+
| quotation_item_id | quotation_id | quotation_item_amount |
+-------------------+--------------+-----------------------+
| 1 | 1 | 500 |
| 2 | 1 | 700 |
| 3 | 1 | 600 |
| 4 | 2 | 200 |
| 5 | 2 | 150 |
| 6 | 3 | 900 |
+-------------------+--------------+-----------------------+
table invoice
+--------------+-------------------+------------------+
| invoice_id | client_project_id | invoice_number |
+--------------+-------------------+------------------+
| 1 | 23 | I/01/2020/001 |
| 2 | 17 | I/01/2020/002 |
| 3 | 54 | I/01/2020/003 |
+--------------+-------------------+------------------+
table invoice_item
+-------------------+--------------+-----------------------+
| invoice_item_id | invoice_id | invoice_item_amount |
+-------------------+--------------+-----------------------+
| 1 | 1 | 500 |
| 2 | 1 | 700 |
| 3 | 1 | 600 |
| 4 | 2 | 200 |
| 5 | 2 | 150 |
| 6 | 3 | 900 |
+-------------------+--------------+-----------------------+
The result that I need to obtain is:
SUM of quotation_item_amount and SUM of invoice_item_amount PER client_project_id
To query WHERE SUM(invoice) < SUM(quotation)
Here is my latest try at the query
SELECT
SUM(quotation_item.quotation_item_amount) as quot_amt,
SUM(invoice_item.invoice_item_amount) as inv_amt,
data_client_project.client_project_id,
data_client.client_name
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id
JOIN (
SELECT quotation_id,
SUM(c.quotation_item_amount) as quot_amt
FROM quotation_item c
GROUP BY c.quotation_id
) quotitem
ON b.quotation_id = quotitem.quotation_id
JOIN (
SELECT invoice_id,
SUM(e.invoice_item_price) as inv_amt
FROM invoice_item e
GROUP BY e.invoice_id
) invitem
ON i.invoice_id = invitem.invoice_id
However, this results in multiple duplicate rows of the quotation_item_amount and invoice_item_amount.
Have tried using UNION / UNION ALL and several other queries which just do not work.
Thank you for all your suggestions.
It looks like you are trying to aggregate along two different dimensions at the same time. The solution is to pre-aggregate along each dimension:
SELECT *
FROM data_client_project cp LEFT JOIN
(SELECT q.client_project_id,
SUM(qi.quotation_item_amount * qi.quotation_item_qty) as quot_amt
FROM quotation q JOIN
quotation_item qi
ON qi.quotation_id = q.quotation_id
GROUP BY q.client_project_id
) q
USING (client_project_id) LEFT JOIN
(SELECT i.client_project_id,
SUM(invoice_item_price) as inv_amt
FROM invoice i JOIN
invoice_item ii
ON i.invoice_id = ii.invoice_id
GROUP BY i.client_project_id
) i
USING (client_project_id);
Two notes about your style.
First, you are using arbitrary letters for table aliases. This makes the query quite hard to follow and becomes quite awkward if you add new tables, remove tables, or rearrange the names. Use abbreviations for the tables. Much easier to follow.
Second, I don't really recommend SELECT * for such queries. But, you can avoid duplicated column by replacing ON with USING.
I may be missing something, but your table descriptions do not include a example for data_client or data_client_project Given your example, I expect your row expansion is coming from the first 3 joins.
Make sure that the below is giving you the list of data you want first, then try joining in the calculation:
SELECT *
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id;
#you may want to append the above with a limit 100 for testing.
if you have duplicated rows form the main query then add distinct for obatin a only distinct rows
and andd the where conditio for filtering the result by quotitem.quot_amt < invitem.inv_amt
SELECT distinct a.*, b.*, d.*, i.*
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id
JOIN (
SELECT quotation_id,
SUM(c.quotation_item_amount * c.quotation_item_qty) as quot_amt
FROM quotation_item c
GROUP BY c.quotation_id
) quotitem ON b.quotation_id = quotitem.quotation_id
JOIN (
SELECT invoice_id,
SUM(e.invoice_item_price) as inv_amt
FROM invoice_item e
GROUP BY e.invoice_id
) invitem ON i.invoice_id = invitem.invoice_id
WHERE quotitem.quot_amt < invitem.inv_amt

PDO Query : Count related and repeated values then inner join

I work with PHP and PDO.
So I have 2 tables like,
Table 1
| id | name | age |
| 1 | John | 25 |
| 2 | Tom | 32 |
| 3 | James| 45 |
Table 2
| id | Comment | Link |
| 1 | some text | 3 |
| 2 | some text | 3 |
| 3 | some text | 1 |
So, Link column numbers represent id's in table1. For example Link = 3s in table 2 represent James in table 1. I need a query which brings all table1's data and also a number of repeated value for related Link column which comes from table2.
For example, the query should give me (let's choose James),
| id | name | age | Value |
| 3 | James | 45 | 2 |
value=2, because there are two 3s in link column which related to James
I tried somethings but got lots of errors.
I think you just need the GROUP BY
SELECT a.id,
a.name,
a.age,
count(*) as value
FROM table1 a
JOIN table2 b ON a.id = b.link
GROUP BY a.id, a.name, a.age
If you really want just one row then add WHERE
SELECT a.id,
a.name,
a.age,
count(*) as value
FROM table1 a
JOIN table2 b ON a.id = b.link
WHERE a.name = 'James'
GROUP BY a.id, a.name, a.age
or use subquery
SELECT a.id,
a.name,
a.age,
(SELECT count(*) FROM table2 b WHERE a.id = b.link) as value
FROM table1 a
WHERE a.name = 'James'

MYSQL statement: lookup how many records exist how many times in other table

I have 2 database tables:
Table 1:
+---------+-------+-------------+
| Page | Title | Description |
+---------+-------+-------------+
| Apple | ..... | ........... |
| Orange | ..... | ........... |
| Pear | ..... | ........... |
| Grapes | ..... | ........... |
+---------+-------+-------------+
Table 2:
+----------+-------------+
| Link | Page |
+----------+-------------+
| Website1 | Apple |
| Website2 | Orange |
| Website3 | Apple |
| Website4 | Orange |
| Website5 | Apple |
| Website6 | Pear |
| Website7 | Apple |
| Website8 | Grapes |
| Website9 | Grapes |
+----------+-------------+
I want to know/return how many pages from Table 1 are referenced in Table 2 and how many times they are referenced. (I DON'T want to know how many times EACH page in Table 1 is referenced in Table 2).
So in this example:
1 page is referenced 1 time (Pear),
2 pages are referenced 2 times (Grapes and Orange) &
1 page is referenced 4 times.
What kind of SQL statement would I use to get this?
Following query should do..
SELECT COUNT(1) NoOfPages,CNT ReferencedTimes
FROM
(
SELECT T2.PAGE,COUNT(1) CNT
FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.PAGE = T2.PAGE
GROUP BY T2.PAGE
)T
GROUP BY CNT
I think the following statement will fit:
SELECT count(*) FROM Table2 WHERE (Table2.Page IN (SELECT Page FROM Table1));
Use This query
Select table2.page,cnt(table2.page)
from table1 inner join table2
On table1.Page=table2.Page group by table2.page
SELECT (GROUP_CONCAT(DISTINCT page)) AS Page,page_count
FROM
(SELECT table1.Page as page,COUNT(*) as page_count
FROM table1 INNER JOIN table2 ON table1.Page=table2.Page
GROUP BY table1.Page)
as T GROUP BY page_count
Hope this helps
If what you are seeking is X page was referenced N times, the below query will achieve that:
SELECT COUNT(t1.page), t2.count
FROM table1 t1
INNER JOIN (SELECT page,COUNT(*) AS count FROM table2 GROUP BY page) t2 ON t1.page=t2.page
GROUP BY t2.count
Try this query, it will make a left join and tell you how many times item is referenced in table2, if count is zero than no reference in the other table
SELECT table1.Page, count(table2.Page) as count
FROM table1
LEFT JOIN table2 ON table2.Page = table1.Page
GROUP BY table1.Page

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 query for delete row if two columns are equal

How to delete all rows from a mysql table if values of two columns are equal
Example Table
invoice_id| item_id | name | invoiced_qty | received_qty
---------------------------------------------------------
| 1 | 1 | item1 | 3 | 2
| 2 | 2 | item2 | 5 | 5
| 3 | 1 | item3 | 4 | 3
| 4 | 2 | item4 | 2 | 2
| 5 | 1 | item5 | 5 | 5
After deleting table needs to retains
invoice_id| item_id | name | invoiced_qty | received_qty
---------------------------------------------------------
| 1 | 1 | item1 | 3 | 2
| 3 | 1 | item3 | 4 | 3
The select query which i created is
SELECT * FROM table1 A
INNER JOIN table1 B ON A.item_id = B.item_id
AND A.invoice_id = B.invoice_id
AND A.invoiced_qty = B.received_qty
Thanks
Why not just SQL Fiddle:
DELETE FROM table1
WHERE invoiced_qty = received_qty
Your edit does not change anything. He is the SQL Fiddle demonstrating your SELECT query. According to your sample data A.invoice_id will never equal B.invoice_id. So you will not get any results.
Try this :
DELETE FROM table1 A
INNER JOIN table1 B ON A.item_id = B.item_id
WHERE A.invoiced_qty = B.received_qty
You could simply wrap your select statement and select values to be deleted by id, like this:
DELETE FROM table1
WHERE item_id IN (SELECT item_id FROM table1 A
INNER JOIN table1 B ON A.item_id = B.item_id
AND A.invoice_id = B.invoice_id
AND A.invoiced_qty = B.received_qty)
however you should accept answer by Linger as it is more straightforward solution, mine was to indicate that if you have something selected usually you can wrap and delete.

Categories