MySQL query select from multiple table depending on a certain condition - mysql

I have two tables as follow:
table internetclient
(id,full_name,location,phone_number)
table internetclientdetails
(incdid,icid,date_sub, date_exp,isPaid,profile_sub)
the data in two table is as follow:
client
--------------------------------------------------------
id full_name location phone_number
-------------------------------------------------------
4 Joe Amine beirut 03776132
5 Mariam zoue beirut 03556133
client_subscription
--------------------------------------------------------------------------
incdid icid date_sub date_exp isPaid sub_price
----------------------------------------------------------------------------
6 4 2018-01-01 2018-01-30 0 2000
7 5 2017-01-01 2017-01-30 0 1000
8 4 2018-03-01 2018-03-30 1 50000
9 5 2018-05-01 2019-05-30 1 90000
note : incdid stands for internetClientDetailsId
and icid stands for internetClientId
Problem
I want to make a query that return client name along with all details depending on the latest client subscription date, the result should be as follow:
------------------------------------------------------------
full_name client_id date_sub sub_price
------------------------------------------------------------
Joe Amine 4 2018-03-01 50000
Mary 5 2018-05-01 90000
What i am tring
SELECT * FROM client c LEFT JOIN client_subscription c_s on c.id=c_s.client_id
UNION
SELECT * FROM client c RIGHT JOIN client_subscription c_S on c.id=c_s.client_id
WHERE
c.sub_date=(SELECT MAX(sub_date) from client_subscription c_s INNER JOIN client c on c.id=c_s.client_id GROUP BY c_s.client_id
i have been working on it all the night. Any help is appreciated a lot.

To get client_subscription for each client you could use a self join
select c.name, a.client_id, a.date_sub, a.sub_price
from client_subscription a
join (
select client_id, max(date_sub) date_sub
from client_subscription
group by client_id
) b on a.client_id = b.client_id and a.date_sub = b.date_sub
join client c on a.client_id = c.id
order by a.date_sub
Demo
Or using left join
select c.name, a.client_id, a.date_sub, a.sub_price
from client_subscription a
left join client_subscription b on a.client_id = b.client_id and a.date_sub < b.date_sub
join client c on a.client_id = c.id
where b.client_id is null
order by a.date_sub
Demo
Using your updated data set updated queries are
select c.full_name, a.icid, a.date_sub, a.sub_price
from internetclientdetails a
join (
select icid, max(date_sub) date_sub
from internetclientdetails
group by icid
) b on a.icid = b.icid and a.date_sub = b.date_sub
join internetclient c on a.icid = c.id
order by a.date_sub;
select c.full_name, a.icid, a.date_sub, a.sub_price
from internetclientdetails a
left join internetclientdetails b on a.icid = b.icid and a.date_sub < b.date_sub
join internetclient c on a.icid = c.id
where b.icid is null
order by a.date_sub
Updated Demo

Hi try below sample might help you.
DECLARE #tblClient AS TABLE (ID INT , Name varchar(100))
DECLARE #tblClientSub As TABLE (id INT,client_id INT,date_sub DATE,sub_price INT)
INSERT INTO #tblClient (id,Name)
VALUES
(1,'Linda'),
(2,'Mary'),
(3,'Joe')
INSERT INTO #tblClientSub(Id,client_id , date_sub , sub_price)
VALUES
(1,1,'2018/01/01',50),
(2,2,'2018/02/01',50),
(3,2,'2018/03/01',30),
(4,2,'2018/04/01',30),
(5,3,'2018/01/01',50),
(6,3,'2018/07/01',50),
(7,1,'2018/02/01',40)
SELECT c.Id,c.Name,cs.date_sub,cs.sub_price
FROM #tblClient c
CROSS APPLY (SELECT TOP (1)date_sub,sub_price
FROM #tblClientSub
WHERE client_id = c.Id
ORDER BY date_sub DESC) cs

select c.name as 'client_name',cs.client_id,max(cs.sub_date) as 'date_sub',cs.sub_price from client c ,
client_subscription cs where cs.client_id=c.id group by cs.client_id,cs.sub_price;

Try this
SELECT c.Name, c.id , MAX(date_sub), sub_price FROM client c LEFT JOIN client_subscription c_s on c.id=c_s.client_id
GROUP BY c.id
ORDER BY c.id ASC

Related

Issue getting while fetching data using joins

I have four table and structure as below :
1)Budget
id Budget_name
1 test1
2 test2
3 test3
2)Yearly Budget
id amount_yearly budgetid
1 1000 1
2 2000 2
3 5000 3
ri_spent
id Spent_amount budgetid
1 100 2
2 100 2
3 200 3
4)FI_spent
id Spent_amount budgetid
1 100 2
2 100 3
3 200 3
i want to fetch data accourding to or based on first budget table id
below is the query i was trying:
select d.centers as Cost_Center,
ud.BUDGET_ANNUAL_AMOUNT as Annual_Budget,
l.LEAD_ID as Lead_Id,
l.AMOUNT as Lead_Amount,
f.FINANCEADD_ID as Finance_Id,
f.AMOUNT as Finance_Amount
from Cost_centers as d
inner join ANNUAL_BUDGET_BUDGET_CENTER as ud on d.id = ud.BUDGET_ID
inner join RI_DETAILS as l on l.COST_CENTER = d.id
inner join F_RI_DETAILS as f on f.COST_CENTER = d.id
ORDER BY d.id DESC
I want output of the following way:
Id Name ri_id FI_ID RI_Spent_Amount FI_Spent_Amount Annual_Buget
1 test1 1000
2 test2 1 1 100 200 1000
2 test2 2 100 2000
3 test3 3 2 300 100 2000
3 test3 3 200 2000
Any way if possible then please help me.
I want to minus annual budget with spent_amount later.
If possible then help me .
Please Try This Query ,
select b.id ,
b.Budget_name,
y.id,
y.amount_yearly,
r.id,
r.ri_spent,
f.id,
f.Spent_amount
from Budget b
INNER JOIN Yearly_Budget y on y.budgetid =b.id
INNER JOIN ri_spent r on r.budgetid =b.id
INNER JOIN FI_spent f on f.budgetid =b.id
ORDER BY b.id DESC
Could you please use left join instead of inner join. Requirement and sql arent matching so i may be little off. But you can get the idea.
select d.centers as Cost_Center,
ud.BUDGET_ANNUAL_AMOUNT as Annual_Budget,
l.LEAD_ID as Lead_Id,
l.AMOUNT as Lead_Amount,
f.FINANCEADD_ID as Finance_Id,
f.AMOUNT as Finance_Amount
from Cost_centers as d -- I assume this is the budget table
left outer join ANNUAL_BUDGET_BUDGET_CENTER as ud on d.id = ud.BUDGET_ID
left outer join RI_DETAILS as l on l.COST_CENTER = d.id
left outer join
(select sum(FINANCEADD_ID) FINANCEADD_ID,sum(AMOUNT) AMOUNT,id from
F_RI_DETAILS group by id) as f
on f.COST_CENTER = l.id
ORDER BY d.id DESC

SQL select and compare

I am trying to retrieve everything from client and bond table where the client.id is not equal to bond.client and bond client.bond is not equal to bond.id. My query did not work and returns the whole list instead. How can i solve this problem? My query wants to output 4 , 5 from client table and 5, 5 from bond table as the result
Client table
Id Bond
1 2
2 3
4 5
Bond table
Id Client
2 1
3 2
5 5
.
SELECT * FROM `client_table`
INNER JOIN `bond_table`
where client_table.id != bond_table.client and client_table.bond != bond_table.id
Please try this:
SELECT c.ClientID, c.BondID from client_table c
left join bond_table b
on c.clientID = b.clientID
where b.clientID is null
UNION
SELECT b.ClientID, b.BondID from bond_table b
left join client_table c
on c.clientID = b.clientID
where c.clientID is null
could be using not in clause
SELECT * FROM `client_table`
INNER JOIN `bond_table` on client_table.id
not in ( select bond_table.client from bond)
AND client_table.bond not in ( select bond_table.id from bond)
but based on the resukt you show in the comment you should use OR (and not AND)
SELECT * FROM `client_table`
INNER JOIN `bond_table` on client_table.id
not in ( select bond_table.client from bond)
OR client_table.bond not in ( select bond_table.id from bond)

Left Join most recent record, if one exists

I have a table of people, and I want to pull the most recent record of event, but there may not be one.
So my problem is that even though I'm left joining to make sure I'm getting a record for each person, I'm only bringing back people that have events because I'm pulling the Max of a date as a criteria.
SELECT *
FROM tbl_people
LEFT JOIN tbl_events ON
tbl_people.People_UID = tbl_events.People_UID
WHERE tbl_people.Active = 1
AND (
SELECT MAX(Event_Date) FROM tbl_events
)
Table People would have the following
People_UID
Table Events would have the following
Event_UID, People_UID, Event_Name, Event_Date
Like I said, what I'd like is an output like this:
Jen, Had a Baby, 7/10/2015
Shirley
Susan
Megan, Had a Baby, 8/5/2014
etc.
I hope that makes sense.
select * from
( SELECT *, row_number() over (partition by tbl_people.name order by tbl_events.Event_Date desc) as rn
FROM tbl_people
LEFT JOIN tbl_events
ON tbl_people.People_UID = tbl_events.People_UID
WHERE tbl_people.Active = 1 ) t
where t.rn = 1
It depends on the database.
If you're using MySQL, you could simply put the correlated subquery into the on clause of the outer join like this:
select *
from tbl_people p
left join tbl_events_latest e
on p.people_uid = e.people_uid
and e.event_date =
(select max(x.event_date) from tbl_events x where x.people_uid = e.people_uid)
where p.active = 1
In other databases, that might not be so. For example, in Oracle, you'd get an error. You could alternatively run:
with tbl_events_latest as
(select *
from tbl_events e
where event_date = ( select max(x.event_date)
from tbl_events x
where x.people_uid = e.people_uid ) )
select *
from tbl_people p
left join tbl_events_latest e
on p.people_uid = e.people_uid
where p.active = 1
One way to do this is to use a correlated subquery in the join that checks that there doesn't exists any event for the same person with a later date:
SELECT *
FROM tbl_people p
LEFT JOIN tbl_events e
ON p.People_UID = e.People_UID
AND NOT EXISTS (
SELECT 1 FROM tbl_Events
WHERE e.People_UID = People_UID
AND Event_Date > e.Event_Date
)
WHERE p.Active = 1
It might not be the most efficient solution though; maybe limiting the left joined set first is better. (Or come to think of it the exists should be better).
Given a sample data set like:
People_UID Event_UID People_UID Event_Name Event_Date
Jen 1 Jen Had a Baby 2015-07-10
Jen 3 Jen Bought a horse 2013-07-10
Shirley NULL NULL NULL NULL
Susan NULL NULL NULL NULL
Megan 2 Megan Had a Baby 2014-08-05
Megan 4 Megan Had another Baby 2015-08-05
This would be the result:
People_UID Event_UID People_UID Event_Name Event_Date
Jen 1 Jen Had a Baby 2015-07-10
Shirley NULL NULL NULL NULL
Susan NULL NULL NULL NULL
Megan 4 Megan Had another Baby 2015-08-05
Using joins it could look like this:
SELECT *
FROM tbl_people p
LEFT JOIN (
SELECT e.*
FROM tbl_events e
JOIN (
SELECT PEOPLE_UID, MAX(EVENT_DATE) MDATE
FROM tbl_Events GROUP BY People_UID
) A ON A.MDATE = E.event_date AND e.People_UID = A.People_UID
) B ON p.People_UID = b.People_UID
WHERE p.Active = 1
In case of Sql Server you can use OUTER APPLY:
SELECT *
FROM tbl_people p
OUTER APPLY(SELECT TOP 1 Event_Date
FROM tbl_events e
WHERE p.People_UID = e.People_UID
ORDER BY Event_Date DESC)oa
WHERE p.Active = 1
Or if you want to select just date then:
SELECT *
FROM tbl_people p
OUTER APPLY(SELECT MAX(Event_Date) AS Event_Date
FROM tbl_events e
WHERE p.People_UID = e.People_UID)oa
WHERE p.Active = 1

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';

MYSQL inner join 2 tables and sum()

I am unable to get sum() after joining 2 tables, one is HEADER AND DETAIL. It just gives only 0 result for the below sql statement. Need some help:
My tables:
INVHDR:
Invno, Invdate, Ac_code
100 2013-04-01 2
101 2013-04-30 2
INVDTLS:
Invno, Prod_desc, Amount
100 Argon 155
100 Argon 250
101 Oxygen 322
101 Oxygen 065
Desired result:
Sum of amts: 405
MYSQL statement to inner join and sum()
SELECT
a.Invno, a.Ac_code, a.Invdate, b.*
FROM INVHDR a
INNER JOIN (
SELECT
Invno, Prod_desc, SUM( Amount ) AS amts
FROM INVDTLS
WHERE Prod_desc='Argon'
) AS b ON a.Invno = b.Invno
WHERE
a.Ac_code='2'
AND a.Invdate BETWEEN '2013-04-01'
AND '2013-04-30'
GROUP BY a.Ac_code
Why are you writing such a complicated Query, try this:
SELECT sum(b.Amount)
FROM INVHDR a
INNER JOIN INVDTLS b
ON a.Invno = b.Invno
WHERE a.Ac_code='2'
AND a.Invdate BETWEEN '2013-04-01' AND '2013-04-30'
AND b.Prod_desc='Argon'
--Group by b.Prod_desc,a.Invno, a.Ac_code
Here is the SQL Fiddle
check http://www.sqlfiddle.com/#!2/86377/8 Thank you #Luv
SELECT
a.Invno, a.Ac_code, b.Prod_desc, SUM(b.Amount) AS Amount
FROM INVHDR a
INNER JOIN INVDTLS b ON a.Invno = b.Invno
WHERE
a.Ac_code = 2 -- a.Ac_code='2'
AND a.Invdate BETWEEN '2013-04-01' AND '2013-04-30'
AND b.Prod_desc='Argon'
group by a.Invno, a.Ac_code, b.Prod_desc