How to create a right select query from 3 tables (SUM)? - sql

I have 3 tables:
+-----+---------+
|cl_id| name |
+-----+---------+
| 1 | adaf |
| 2 | rich | - clients
| 3 | call |
| 4 | alen |
| 5 | courney |
| 6 | warren |
+-----+---------+
+-----+---------+
|cl_id| data |
+-----+---------+
| 1 | 13 |
| 2 | 1000 | - table1
| 5 | 0 |
| 6 | 0 |
+-----+---------+
+-----+---------+
|cl_id| data |
+-----+---------+
| 2 | -355 | - table2
| 3 | 35 |
| 3 | 10 |
| 5 | 46 |
| 5 | 50 |
| 5 | 10 |
+-----+---------+
And I have to combine those three tables, so the result should be:
+-----+---------+--------+---------+
|cl_id| name |data_tb1|data_tb2 |
+-----+---------+--------+---------+
| 1 | adaf | 13 | 0 |
| 2 | rich | 1000 | -355 |
| 3 | call | 0 | 45 |
| 4 | alen | 0 | 0 |
| 5 | courney| 0 | 106 |
| 6 | warren | 0 | 0 |
+-----+---------+--------+---------+
It should output all clients and theirs SUM(data) from table1 and table2. clients goes one-to-more.
Thanks in advance

Simply using LEFT JOIN and GROUP BY
SELECT c.cl_id,
c.name,
COALESCE(SUM(t1.data), 0) AS data_tb1,
COALESCE(SUM(t2.data), 0) AS data_tb2
FROM clients c
LEFT JOIN table1 t1 ON c.cl_id = t1.cl_id
LEFT JOIN table2 t2 ON c.cl_id = t2.cl_id
GROUP BY c.cl_id,
c.name
ORDER BY c.cl_id;

If you are using SQL Server then simple Use Left Join as below :
SELECT C.cl_id,
C.name,
SUM(ISNULL(T.data, 0)) data_tb1,
SUM(ISNULL(T1.data, 0)) data_tb2
FROM
(
SELECT *
FROM clients
) C
LEFT JOIN table1 T ON T.cl_id = C.cl_id
LEFT JOIN table2 T1 ON T1.cl_id = C.cl_id
GROUP BY C.cl_id,
C.name
ORDER BY C.cl_id;
Desired Output :
+-----+---------+--------+---------+
|cl_id| name |data_tb1|data_tb2 |
+-----+---------+--------+---------+
| 1 | adaf | 13 | 0 |
| 2 | rich | 1000 | -355 |
| 3 | call | 0 | 45 |
| 4 | alen | 0 | 0 |
| 5 | courney| 0 | 106 |
| 6 | warren | 0 | 0 |
+-----+---------+--------+---------+

Related

SQL Merge two Tables

Let's say I have these 2 tables:
ArticleTBL
+---------+----------+-------------+------------+
|articleid| typeid | price | user |
+---------+----------+-------------+------------+
| 0 | 2 | 1 | 122 |
| 1 | 3 | 2 | 344 |
| 2 | 3 | 1 | 455 |
| 3 | 1 | 4 | 34 |
+---------+----------+-------------+------------+
TypeTBL
+---------+----------+-------------+
|typeid | type | factory |
+---------+----------+-------------+
| 0 | wooden | factry1 |
| 1 | plastic | factry2 |
| 2 | metal | factry3 |
| 3 | sth. | factry4 |
+---------+----------+-------------+
How do I request all this information only with articleid for each row?
Isn't this what you want? Read more
SELECT a.articleid,
a.price.a.USER,
t.typeid,
t.type,
t.factory
FROM form ArticleTBL a
INNER JOIN typetbl t
ON a.typeid = t.typeid
WHERE a.articleid = 0

Need query for JOIN four tables with some conditions?

I have the following four tables:
1) mls_user
2) mls_category
3) bonus_point
4) mls_entry
In mls_user table values are like below:
*-------------------------*
| id | store_id | name |
*-------------------------*
| 1 | 101 | sandeep |
| 2 | 101 | gagan |
| 3 | 102 | santosh |
| 4 | 103 | manu |
| 5 | 101 | jagveer |
*-------------------------*
In mls_category table values are like below:
*---------------------------------*
| cat_no | store_id | cat_value |
*---------------------------------*
| 20 | 101 | 1 |
| 21 | 101 | 4 |
| 30 | 102 | 1 |
| 31 | 102 | 2 |
| 40 | 103 | 1 |
| 41 | 103 | 1 |
*---------------------------------*
In bonus_point table values are like below:
*-----------------------------------*
| user_id | store_id | bonus_point |
| 1 | 101 | 10 |
| 4 | 101 | 5 |
*-----------------------------------*
In mls_entry table values are like below:
*-------------------------------------------------------*
| user_id | store_id | category | distance | status |
*-------------------------------------------------------*
| 1 | 101 | 20 | 10 | Approved |
| 1 | 101 | 21 | 40 | Approved |
| 1 | 101 | 20 | 10 | Approved |
| 2 | 101 | 20 | 5 | Approved |
| 3 | 102 | 30 | 10 | Approved |
| 3 | 102 | 31 | 80 | Approved |
| 4 | 101 | 20 | 15 | Approved |
*-------------------------------------------------------*
And I want below output:
*--------------------------------------------------*
| user name | Points | bonus Point | Total Point |
*--------------------------------------------------*
| Sandeep | 30 | 10 | 40 |
| Santosh | 30 | 0 | 30 |
| Manu | 15 | 5 | 20 |
| Gagan | 5 | 0 | 5 |
| Jagveer | 0 | 0 | 0 |
*--------------------------------------------------*
I tell the calculation of how the points will come for user Sandeep.
Points = ((10+10)/1 + 40/4)=30
Here 1 and 4 is cat value which comes from mls_category.
I am using below code for a particular user but when i
SELECT sum(t1.totald/c.cat_value) as total_distance
FROM mls_category c
join (
select sum(distance) totald, user_id, category
FROM mls_entry
WHERE user_id=1 AND store_id='101' AND status='approved'
group by user_id, category) t1 on c.cat_no = t1.category
I have created tables in online for checking
DEMO
Computing the points (other than the bonus points) requires a separate join between the mls_entry and mls_category tables. I would do this in a separate subquery, and then join this to the larger query.
Here is one approach:
SELECT
u.name,
COALESCE(t1.points, 0) AS points,
COALESCE(b.bonus_point, 0) AS bonus_points,
COALESCE(t1.points, 0) + COALESCE(b.bonus_point, 0) AS total_points
FROM mls_user u
LEFT JOIN
(
SELECT e.user_id, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c
ON e.store_id = c.store_id AND e.category = c.cat_no
GROUP BY e.user_id
) t1
ON u.id = t1.user_id
LEFT JOIN bonus_point b
ON u.id = b.user_id
ORDER BY
total_points DESC;
This is the output I am getting from the above query in the demo you setup:
The output does not match exactly, because you have (perhaps) a typo in Santosh's data in your question, or otherwise the expected output in your question has a typo.

Sum data from two tables with different number of rows

There are 3 Tables (SorMaster, SorDetail, and InvWarehouse):
SorMaster:
+------------+
| SalesOrder |
+------------+
| 100 |
| 101 |
| 102 |
+------------+
SorDetail:
+------------+------------+---------------+
| SalesOrder | MStockCode | MBackOrderQty |
+------------+------------+---------------+
| 100 | PN-1 | 4 |
| 100 | PN-2 | 9 |
| 100 | PN-3 | 1 |
| 100 | PN-4 | 6 |
| 101 | PN-1 | 6 |
| 101 | PN-3 | 2 |
| 102 | PN-2 | 19 |
| 102 | PN-3 | 14 |
| 102 | PN-4 | 6 |
| 102 | PN-5 | 4 |
+------------+------------+---------------+
InvWarehouse:
+------------+-----------+-----------+
| MStockCode | Warehouse | QtyOnHand |
+------------+-----------+-----------+
| PN-1 | A | 1 |
| PN-2 | B | 9 |
| PN-3 | A | 0 |
| PN-4 | B | 1 |
| PN-1 | A | 0 |
| PN-3 | B | 5 |
| PN-2 | A | 9 |
| PN-3 | B | 4 |
| PN-4 | A | 6 |
| PN-5 | B | 0 |
+------------+-----------+-----------+
Desired Results:
+------------+-----------------+--------------+
| MStockCode | SumBackOrderQty | SumQtyOnHand |
+------------+-----------------+--------------+
| PN-1 | 10 | 10 |
| PN-2 | 28 | 1 |
| PN-3 | 17 | 5 |
| PN-4 | 12 | 13 |
| PN-5 | 11 | 6 |
+------------+-----------------+--------------+
I have been going around in circles with no end in sight. Seems like it should be simple but just can't wrap my head around it. The SumBackOrderQty obviously getting counted twice as the SumQtyOnHand is evaluated. To this point I have been doing the calculations in the PHP instead of the select statement but would like to clean things up a bit where possible.
Current query statement is:
SELECT SorDetail.MStockCode,
SUM(SorDetail.MBackOrderQty) AS 'SumMBackOrderQty',
SUM(InvWarehouse.QtyOnHand) AS 'SumQtyOnHand'
FROM SysproCompanyJ.dbo.SorMaster SorMaster,
SysproCompanyJ.dbo.SorDetail SorDetail LEFT OUTER JOIN SysproCompanyJ.dbo.InvWarehouse InvWarehouse
ON SorDetail.MStockCode = InvWarehouse.StockCode
WHERE SorMaster.SalesOrder = SorDetail.SalesOrder
AND SorMaster.ActiveFlag != 'N'
AND SorDetail.MBackOrderQty > '0'
AND SorDetail.MPrice > '0'
GROUP BY SorDetail.MStockCode
ORDER BY SorDetail.MStockCode ASC
Without providing the complete picture, in terms of your RDBMS, database schema, a description of the problem you're trying to solve and sample data that matches the aforementioned, the following is just an illustration of what a solution based on Barmar's comment could look like:
SELECT SD.MStockCode,
SD.SumBackOrderQty,
IW.SumQtyOnHand
FROM (SELECT MStockCode,
SUM(MBackOrderQty) AS `SumBackOrderQty`
FROM SorDetail
JOIN SorMaster ON SorDetail.SalesOrder=SorMaster.SalesOrder
WHERE SorMaster.ActiveFlag != 'N'
AND SorDetail.MBackOrderQty > 0
AND SorDetail.MPrice > 0
GROUP BY MStockCode) AS SD
LEFT JOIN (SELECT MStockCode,
SUM(QtyOnHand) AS `SumQtyOnHand`
FROM InvWarehouse
GROUP BY MStockCode) AS IW ON SD.MStockCode=IW.MStockCode
ORDER BY SD.MStockCode;
Here's one approach:
select MStockCode,
(select sum(MBackOrderQty) from sorDetail as T2
where T2.MStockCode = T1.MStockCode ) as SumBackOrderQty,
(select sum(QtyOnHand) from invWarehouse as T3
where T3.MStockCode = T1.MStockCode ) as SumQtyOnHand
from
(
select mstockcode from sorDetail
union
select mstockcode from invWarehouse
) as T1
In a fiddle here: http://sqlfiddle.com/#!9/fdaca/6
Though my SumQtyOnHand values don't match yours (as #Gordon pointed out).

trying to write a query with Table A,B where Cond1: A.pc=B.pc & Cond2: (preferred (A.sub = B.Sub) or else any 1 row that meet only Cond1)

I trying to get the result table to contain rows where
Condition1: A.pc=B.pc AND
Condition2: (preferred (A.sub = B.Sub) or
else any one row that satisfy only Condition1)
I have tried the following inner join query and few other join and sub-query but can not figure out exact way to write a query with above strange condition.
SELECT * FROM tblA AS A INNER JOIN tblB AS B
ON A.sub=B.sub
WHERE A.pc=B.pc
tblA
-------------------
| id | pc | sub |
-------------------
| 0 | 5 | abc |
| 1 | 8 | def |
| 2 | 6 | ghi |
| 3 | 2 | jkl |
| 4 | 7 | mno |
| 5 | 19 | pqr |
-------------------
tblB
-------------------------
| pc | sub | uml | ull |
-------------------------
| 3 |arm | 1 | 1 |
| 3 |gtk | 1 | 2 |
| 3 |lmn | 1 | 3 |
| 3 |pop | 1 | 4 |
| 5 |abc | 1 | 5 |
| 5 |hlq | 1 | 6 |
| 5 |pon | 2 | 1 |
| 5 |qrt | 2 | 2 |
| 7 |alo | 2 | 3 |
| 7 |mno | 2 | 4 |
| 7 |ghm | 2 | 5 |
| 7 |stm | 2 | 6 |
| 9 |mck | 2 | 7 |
| 9 |plo | 3 | 1 |
| 9 |rtk | 3 | 2 |
| 9 |ert | 3 | 3 |
| 6 |gji | 3 | 4 |
| 6 |ghi | 3 | 5 |
| 6 |yux | 4 | 1 |
| 6 |del | 4 | 2 |
| 2 |jkl | 4 | 3 |
| 2 |jll | 5 | 4 |
| 2 |uin | 6 | 1 |
| 2 |tro | 6 | 2 |
| 19 |ppm | 6 | 3 |
| 19 |kde | 6 | 4 |
| 19 |grp | 6 | 5 |
| 19 |sho | 6 | 6 |
-------------------------
Expected Result Table:
-------------------------------
| id | pc | sub | uml | ull |
-------------------------------
| 0 | 5 |abc | 1 | 5 |
| 2 | 6 |ghi | 3 | 5 |
| 3 | 2 |jkl | 4 | 3 |
| 4 | 7 |mno | 2 | 4 |
| 5 | 19 |ppm | 6 | 3 | *
-------------------------------
* notice this is a arbitrary row as (A.sub=B.sub) not found
** notice there is no result for id=1 as pc=8 do not exist in tblB
Until someone comes up with a better answer, here is some code that does what you want.
Please, note it might not be a good solution in terms of performance (espcially as your tables grow).
SELECT *
FROM (
SELECT tblA.id, tblB.*
FROM tblA INNER JOIN tblB
ON tblA.pc = tblB.pc AND
tblA.id NOT IN (SELECT tblA.id
FROM tblA INNER JOIN tblB
ON tblA.sub = tblB.sub)
GROUP BY tblA.id
UNION
SELECT tblA.id, tblB.*
FROM tblA INNER JOIN tblB
ON tblA.sub = tblB.sub
GROUP BY tblA.id
) AS tu
ORDER BY id ASC;
See, also, this short demo.
One way of doing it I came up with is to repeat a join condition in where clause:
SELECT *
FROM tblA AS A
INNER JOIN tblB AS B
ON A.pc = B.pc
WHERE A.sub = B.sub
OR A.pc = B.pc

SQL query from multiple tables

I am new to SQL, I need some help,
I want to find out confirmed (confirmed=1) reservation date with last name Steven
Can some one help for with the this SQL Query
table_member
+-----------+-----------+
|Member_id | last_name |
+-----------+-----------+
| 1 | David |
| 2 | owen |
| 3 | Tom |
| 4 | Steven |
| 5 | Steven |
| 6 | Steven |
| 7 | Steven |
| 8 | Steven |
| 9 | Steven |
+-----------+-----------+
table_resevation
+-----------+-----------+-----------+-----------+
|resvationID|Member_id | day | month |
+-----------+-----------+-----------+-----------+
| 1 | 1 | 1 | 6 |
| 2 | 1 | 2 | 6 |
| 3 | 2 | 1 | 6 |
| 4 | 4 | 1 | 6 |
| 5 | 4 | 2 | 6 |
| 6 | 5 | 1 | 6 |
| 7 | 5 | 2 | 6 |
| 8 | 7 | 3 | 6 |
+-----------+-----------+-----------+-----------+
Confirm
+-----------+-----------+-----------+
|confirmID |resvationID| confirmed |
+-----------+-----------+-----------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 1 |
| 6 | 6 | 1 |
| 7 | 7 | 0 |
| 8 | 8 | 1 |
+-----------+-----------+-----------+
Does something like this work for you?
SELECT
m.Member_ID, m.Last_Name,
r.Day, r.Month,
c.ConfirmID
FROM
table_member m
INNER JOIN
table_reservation r ON r.Member_ID = m.Member_ID
INNER JOIN
Confirm c ON c.resvationID = r.resvationID
WHERE
m.Last_Name = 'Steven' AND c.confirmed = 1
Select c.*, r.*, m.*
from confirm c
left join table_reservation r on c.reservationID = r.reservationID
left join table_member m on m.member_id = r.Member_id
Where c.confirmed = 1
and m.name = "Steven"
I did not test it, but that should point you to the way.
(Edit: second "where" was a typo)
Apply inner join on all table
select day,month from table_reservation inner join table_member on table_member.member_id=table_reservation.member_id
inner join confirm on confirm.reservationid=table_reservation.reservationid where confirm.confirmid=1
and table_member.last_name like 'Steven'