Inner join on more than 2 tables - mysql

I have 3 different tables balance,received,expenses with following data in it.
Table received:
mysql> select * from received;
+-----+---------+-----------------+---------------------+
| rid | site_id | received_amount | receive_date |
+-----+---------+-----------------+---------------------+
| 1 | 1 | 500 | 2015-08-19 18:16:51 |
| 2 | 1 | 600 | 2015-08-19 18:16:52 |
| 3 | 1 | 500 | 2015-08-20 18:16:52 |
| 4 | 1 | 500 | 2015-08-19 18:16:52 |
+-----+---------+-----------------+---------------------+
Table expenses:
mysql> select * from expenses;
+-----+---------+----------------+---------------------+
| eid | site_id | expense_amount | expense_date |
+-----+---------+----------------+---------------------+
| 1 | 1 | 500 | 2015-08-19 18:17:11 |
+-----+---------+----------------+---------------------+
Table balance:
mysql> select * from balance;
+----------------+---------+---------------+--------------+-----------------+-----------------+------+------+---------------------+
| transaction_id | site_id | account_title | particulars | opening_balance | closing_balance | rid | eid | transaction_date |
+----------------+---------+---------------+--------------+-----------------+-----------------+------+------+---------------------+
| 1 | 1 | test1 | test1 values | 0 | 500 | 1 | NULL | 2015-08-19 18:16:51 |
| 2 | 1 | test1 | test1 values | 500 | 1100 | 2 | NULL | 2015-08-19 18:16:52 |
| 3 | 1 | test1 | test1 values | 1100 | 1600 | 3 | NULL | 2015-08-20 18:16:52 |
| 4 | 1 | test1 | test1 values | 1100 | 1600 | 4 | NULL | 2015-08-19 18:16:52 |
| 5 | 1 | test1 | test1 values | 1600 | 1100 | NULL | 1 | 2015-08-19 18:17:11 |
+----------------+---------+---------------+--------------+-----------------+-----------------+------+------+---------------------+
I am trying to merge the amount of received and expenses into balance table using following query but somehow I am not able to get correct way to get it.
select
b.transaction_id,
b.site_id,
b.account_title,
b.particulars,
b.opening_balance,
r.received_amount,
e.expense_amount,
b.closing_balance,
b.transaction_date
from
balance b
inner join received r
on b.site_id = r.site_id
inner join expenses e
on b.site_id = e.site_id
group by
b.transaction_id;
I am trying to get this output
+----------------+---------+---------------+--------------+-----------------+-----------------+----------------+-----------------+---------------------+
| transaction_id | site_id | account_title | particulars | opening_balance | received_amount | expense_amount | closing_balance | transaction_date |
+----------------+---------+---------------+--------------+-----------------+-----------------+----------------+-----------------+---------------------+
| 1 | 1 | test1 | test1 values | 0 | 500 | NULL | 500 | 2015-08-19 18:16:51 |
| 2 | 1 | test1 | test1 values | 500 | 600 | NULL | 1100 | 2015-08-19 18:16:52 |
| 3 | 1 | test1 | test1 values | 1100 | 500 | NULL | 1600 | 2015-08-20 18:16:52 |
| 4 | 1 | test1 | test1 values | 1600 | NULL | 500 | 1100 | 2015-08-19 18:16:52 |
| 5 | 1 | test1 | test1 values | 1100 | 500 | NULL | 1600 | 2015-08-19 18:17:11 |
+----------------+---------+---------------+--------------+-----------------+-----------------+----------------+-----------------+---------------------+

You are somewhat close. Instead of INNER JOIN, You need to do a LEFT-JOIN to the receipts and expenses. Since your "Balance" table has ALL transactions, it will drive which entry it sees within your underlying support tables. Also, don't just join on the site ID, but just the "rID" and "eID" since they would be your primary keys on the table anyhow.
No need to group by transaction ID as that is the primary key in the balance table and would only have one entry by a given ID.
select
b.transaction_id,
b.site_id,
b.account_title,
b.particulars,
b.opening_balance,
r.received_amount,
e.expense_amount,
b.closing_balance,
b.transaction_date
from
balance b
LEFT join received r
on b.rid = r.rid
AND b.site_id = r.site_id
LEFT join expenses e
on b.eid = e.eid
AND b.site_id = e.site_id
order by
b.site_id,
b.transaction_date

Related

SQL Distinct a column with conditions

I'm working on a query where I need to count distinct CarId row when the column LocationId is not null and get all CarId if its null or 0 but the query that I tried distincts all the CarId even if its null
#LocId int
Select Count(distinct a.CarId) from VehicleDetails a
inner join VehicleDocuments b on a.DocId=b.DocId
left join VehicleShipmentDetails dpg on dpg.VehicleShipmentId= b.VehicleShipmentId
where b.LogicalDelete=0 and a.LogicalDelete=0
and (dpg.LocationId= #LocId or dpg.LocationId= 0 or dpg.LocationId is null)
| ID | CarId | LocationId | DateCreated |
|------+----------------+-----------------+---------------|
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | null | 01/14/2019 |
| 3 | 2 | 0 | 02/03/2019 |
| 4 | 2 | 5 | 12/30/2018 |
| 5 | 4 | 3 | 01/10/2019 |
| 6 | 3 | 5 | 02/14/2019 |
| 7 | 2 | 5 | 03/13/2019 |
Desired output:
| ID | CarId | LocationId | DateCreated |
+------+----------------+-----------------+---------------+
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | null | 01/14/2019 |
| 3 | 2 | 0 | 02/03/2019 |
| 4 | 2 | 5 | 03/13/2019 |
| 5 | 4 | 3 | 01/10/2019 |
| 6 | 3 | 5 | 02/14/2019 |
Current Output
| ID | CarId | LocationId | DateCreated |
+------+----------------+-----------------+---------------+
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | 5 | 01/14/2019 |
| 3 | 4 | 3 | 01/10/2019 |
| 4 | 3 | 5 | 02/14/2019 |
Im getting a count of 4 but i needed to have 6 as the Count
EDIT: My goal is to remove the row to Distinct CarId if the value of the LocationId is Null or 0 but on my Current code, It distincts all CarId that is null,0 and equals to #LocId
You can query something like this, replace your_table by your actual set of data.
SELECT ID, CardId, LocationId, DateCreated
FROM your_table as T
WHERE NOT EXISTS (SELECT *
FROM your_table as T1
WHERE T.ID > T1.ID AND T.CarID = T1.CarID)
In SQL, you can use the statement CASE to manage conditions (just like the "if then else" in other programming languages). In your case this function could help because you have two differents cases to handle.

MySQL Update with Select Join

I have following tables as the simplest form.
Table "pro_details_old"
+------+------------+--------+------------+
| id | project_no | amount | pro_date |
+------+------------+--------+------------+
| 1000 | 001/001 | 50000 | 2018-10-01 |
| 1001 | 001/002 | 25000 | 2018-10-06 |
| 1002 | 002/004 | 75000 | 2018-10-12 |
| 1003 | 002/005 | 65000 | 2018-09-22 |
| 1004 | 002/006 | 10000 | 2018-08-17 |
| 1005 | 003/002 | 12000 | 2018-10-08 |
| 1006 | 003/003 | 145000 | 2018-07-01 |
+------+------------+--------+------------+
Table "pro_details_new"
+------+------------+--------+----------+
| id | project_no | amount | pro_date |
+------+------------+--------+----------+
| 1050 | 001/001 | 50000 | |
| 1051 | 001/002 | 25000 | |
| 1052 | 002/004 | 75000 | |
| 1053 | 002/005 | 65000 | |
| 1054 | 002/006 | 10000 | |
| 1055 | 003/002 | 12000 | |
| 1056 | 003/003 | 145000 | |
+------+------------+--------+----------+
02) So, I need to update issued_date column in "issues" table while comparing project_no of above 02 tables. ref_no & amount columns of "issues" table are already inserted. Expected output as follows.
+----+--------+--------+-------------+
| id | ref_no | amount | issued_date |
+----+--------+--------+-------------+
| 1 | 1050 | 50000 | 2018-10-01 |
| 2 | 1051 | 25000 | 2018-10-06 |
| 3 | 1052 | 75000 | 2018-10-12 |
| 4 | 1053 | 65000 | 2018-09-22 |
| 5 | 1054 | 10000 | 2018-08-17 |
| 6 | 1055 | 12000 | 2018-10-08 |
| 7 | 1056 | 145000 | 2018-07-01 |
+----+--------+--------+-------------+
03) I used the following query.
insert into issues
set issued_date =
(select pro_date
from pro_details_old
where
pro_details_old.project_no = pro_details_new.project_no)
left join pro_details_new on pro_details_new.id = issues.ref_no
04) I can not understand what is the wrong point. Can anyone help me ?
Update Query using join
Select the particular data which you want to update in issuestable using condition
update
issuestable as t3
join (
select
t1.id,
t1.pro_date
from
pro_details_old as t1
inner join pro_details_new as t2 on t1.project_no = t2.project_no
) t4 on t4.id = t3.ref_no
set
t3.issued_date = t4.pro_date
Insert Query
If you want to populate fresh data form pro_details_old & pro_details_new then you can use below insert query
INSERT INTO issues (ref_no, amount, issued_date)
VALUES
(
select
t1.id as ref_no,
t1.amount,
t1.pro_date as issued_date
from
pro_details_old as t1
inner join pro_details_new as t2 on t1.project_no = t2.project_no
)

Select Same Column From 2 Tables into 1 Column in View

I have two column with the same name in different tables.
I want to join them into one column in a view.
Here my first table stocks:
+----------+------------+------------+---------+----------------+--------+
| stock_id | stock_cost | stock_left | item_id | purchasedtl_id | trx_id |
+----------+------------+------------+---------+----------------+--------+
| 1 | 1000 | 0 | 1 | 1 | 1 |
| 2 | 1000 | 5 | 1 | 2 | 2 |
| 3 | 1000 | 1 | 1 | 3 | 4 |
+----------+------------+------------+---------+----------------+--------+
Second table stocks_out
+-------------+----------------+--------------+---------+----------+------------+--------+
| stockout_id | stockout_price | stockout_qty | item_id | stock_id | saledtl_id | trx_id |
+-------------+----------------+--------------+---------+----------+------------+--------+
| 1 | 2000 | 1 | 1 | 1 | 1 | 3 |
+-------------+----------------+--------------+---------+----------+------------+--------+
And I want to join them to be like this trx_id, trx_no, trx_closetime, trx_type stock_id, stock_cost, stockout_id, stock_out_cost, stockout_price, item_id
item_id is the field I want to join in one column.
The current Query is :
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price` from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the current result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
Found it guys.
I just need to add the following query as the column
COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id`
So the query will be like
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price`, COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price | item_id |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL | 1 |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL | 1 |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 | 1 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL | 1 |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+

Get rows that doesn't match on another table

I have this working query that generate data the way i like it to happened but now i want it to add another clause statement that will get rows from tbl_loan_master that was not on the tbl_loanledger.
Example Data:
tbl_borrowers
------------------------------------------
| id | first_name | last_name | deleted |
| 1 | Joe | Smith | 0 |
| 2 | Lily | Mag | 0 |
| 3 | Zen | Green | 0 |
| 4 | Kim | Chan | 0 |
| 5 | Bob | Mac | 1 |
| 6 | Ben | Cork | 0 |
------------------------------------------
tbl_loan_master
----------------------------------------------------------------------
| id | borrowers_id | loan | date_created | due_date | deleted |
| 1 | 4 | 300 | 2016/04/28 | 2017/04/28 | 0 |
| 2 | 1 | 100 | 2016/05/05 | 2017/05/05 | 0 |
| 3 | 2 | 500 | 2016/06/08 | 2017/06/08 | 0 |
| 4 | 1 | 200 | 2016/06/13 | 2017/06/13 | 0 |
| 5 | 3 | 150 | 2016/06/15 | 2017/06/15 | 0 |
| 6 | 6 | 50 | 2016/06/16 | 2017/06/16 | 0 |
----------------------------------------------------------------------
tbl_loanledger
------------------------------------------------------------------------------
| id | borrowers_id | loanmaster_id | payment | balance| date_created | deleted
| 1 | 4 | 1 | 50 | 250 | 2016/05/28 | 0
| 2 | 1 | 2 | 20 | 80 | 2016/05/25 | 0
| 3 | 1 | 2 | 30 | 50 | 2016/06/01 | 0
| 4 | 2 | 3 | 100 | 400 | 2016/06/09 | 0
| 5 | 2 | 3 | 50 | 350 | 2016/06/10 | 0
| 6 | 3 | 4 | 50 | 150 | 2016/06/16 | 0
------------------------------------------------------------------------------
Here is the working query:
$query = "SELECT `tbl_borrowers`.* , `tbl_loanledger`.*, `tbl_loan_master`.*
FROM `tbl_borrowers`
LEFT JOIN `tbl_loanledger`
ON `tbl_borrowers`.id = `tbl_loanledger`.borrower_id
LEFT JOIN `tbl_loan_master`
ON `tbl_loan_master`.id = `tbl_loanledger`.loanmaster_id
WHERE `tbl_borrowers`.deleted = 0 AND `tbl_loanledger`.deleted = 0 AND MONTH ( `tbl_loanledger`.date_created) = MONTH(CURRENT_DATE)
GROUP BY `tbl_loanledger`.borrower_id
ORDER BY `tbl_borrowers`.last_name";
The expected result will output the borrowers with their last transaction on the current month (which is June) in loan ledger and also in loans accounts. Like Ben Cork which is not on the loan ledger, he is on the loan accounts but i want to output him on the result set. The deleted column means if it is 0 it indicates it is active if it is 0 it means it has been deleted.
Expected Result:
|First Name | Last Name | Due Date | Balance |
| Ben | Cork | 2017/06/16 | 50 |
| Joe | Smith | 2017/06/13 | 50 |
| Lily | Mag | 2017/06/08 | 350 |
| Zen | Green | 2017/06/15 | 150 |
Try following;)
select
tb.first_name, tb.last_name, coalesce(tlm.Loan, 0) as Loan, coalesce(t.`Amount Paid`, 0) as `Last Amount Paid`
from tbl_borrowers tb
left join tbl_loan_master tlm
on tb.id = tlm.borrowers_id
left join (
select t1.*
from tbl_loanledger t1
inner join (
select max(id) as id
from tbl_loanledger
group by borrowers_id, loanmaster_id
) t2 on t1.id = t2.id
) t
on tb.id = t.borrowers_id
and tlm.id = t.loanmaster_id
SQLFiddle DEMO HERE

LeftJoin Minus (Right Table data + inner join Data)

TABLE 1)
m_conservationsetting
+------------+-------+------------+
| FacilityId | Unit | CategoryId |
+------------+-------+------------+
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 1 | 1 | 3 |
| 1 | 2 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
+------------+-------+------------+
Unique Key(FacilityId Unit CategoryId)
TABLE 2)
l_maintelog
+------------+------+------------+--------+
| FacilityId | Unit | CategoryId | Status |
+------------+------+------------+--------+
| 1 | 1 | 1 | 0 |
| 1 | 1 | 2 | 1 |
| 1 | 1 | 3 | 0 |
| 1 | 2 | 1 | 0 |
| 2 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
+------------+------+------------+--------+
Result :
+------------+------+------------+
| FacilityId | Unit | CategoryId |
+------------+------+------------+
| 1 | 1 | 2 |
| 1 | 2 | 2 |
+------------+------+------------+
Table1 need to be left Joined with Table2 and it should ommit the join results and show only table1 data as results.
Table1 LeftJoin Table2 - (join Data) for the below query. The condition for getting result is to check the status=0 for the record in Table2
Query
select cs.FacilityId,Cs.Unit,cs.CategoryId
from m_conservationsetting cs
LEFT JOIN l_maintelog ml on
(cs.FacilityId=ml.FacilityId and cs.Unit=ml.Unit)
WHERE (ml.Status=0
)
group by cs.CategoryId
You can use NULL conditional on Second Table's Key column to eliminate result which is there in both tables
Select cs.FacilityId,Cs.Unit,cs.CategoryId
from m_conservationsetting cs
LEFT JOIN l_maintelog ml on
(cs.FacilityId=ml.FacilityId and cs.Unit=ml.Unit)
WHERE (ml.Status=0
and ml.FacilityId IS NULL)
group by cs.CategoryId