Related
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
I have a database with 3 tables records, categories, relational.
records (id, lat, lng)
categories (c_id, c_value)
relational (r_id, c_id)
records
id | lat | lng
----------------------
1 23.57258 -35.28412
2 23.54855 -35.18881
3 23.74128 -35.17469
categories
c_id | c_value
---------------
100 groceries
101 bags
102 drinks
relational
id | c_id
------------
1 100
1 102
2 101
3 100
The relational.r_id = records.id and the relational.c_id = categories.c_id
I want to take pairs from records with different c_value, so I want to make a self join in records and inner join in categories and relational.
I've made this without the self join in records
SELECT id, lat, lng, c_value
FROM records
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE c_value = "V1"
I tried something like this but it didn't work. I have problem with the R1.c_value.
SELECT R1._id, R1.lat, R1.lng, R1.c_value, R2._id, R2.lat, R2.lng,
R2.c_value
FROM records R1, records R2
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE R1.c_value = "groceries" AND R2.c_value = "bags"
Do you know how can I combine those 3 joins in order to take 2 rows from records with the criteria of the other tables?
I want to have an output like this:
For "groceries" and "bags" as c.value
1 | 23.57258 | -35.28412 | groceries | 2 | 23.54855 | -35.18881 | bags
You can self join records table along with categories and relational like this:
SELECT r1.id, r1.lat, r1.lng, r2.id, r2.lat, r2.lng, c.c_value
FROM records r1 JOIN relational rl ON r1.id = rl.r_id
JOIN records r2 ON r2.id = rl.r_id
JOIN categories c ON rl.c_id = c.c_id
WHERE r1.id <> r2.id;
I finally found exactly what I wanted. My query should be like this. Thanks for the help and the idea anyway.
SELECT r1.id, r1.lat, r1.lng, c1.c_value, r2.id, r2.lat, r2.lng, c2.c_value
FROM records r1 JOIN relational rl1 ON rl1.id = r1.id
JOIN categories c1 ON rl1.c_id = c1.c_id
JOIN records r2 JOIN relational rl2 ON rl2.id = r2.id
JOIN categories c2 ON rl2.c_id = c2.c_id
WHERE c1.c_value = "groceries" AND c2.c_value = "bags"
I have been working with SAP Business One right now, and at this moment i was baffled on how to achieve the required query output.
The desired output will be like
SLPName | Customer Name | Jan | Jan-chrgs | Feb | Feb-chrgs | Mar | Mar-chrgs
slp1 | cust1 | 123.00 | 30.00 | 230.00 | 40.00 | 150.00 | 35.00
What have done so far is this, which works perfectly BUt without charges(delivery charges, repair charges, etc.).
SELECT SRNAMe, Customer,
ISNULL([1],0) as [Jan],
ISNULL([2],0) as [Feb],
ISNULL([3],0) as [Mar],
ISNULL([4],0) as [Apr]
FROM (SELECT T2.SlpName SRNAMe,T1.CARDNAME Customer, SUM(T1.DocTotal) as Total,MONTH(T1.Docdate) as [month]
FROM ORDR T1 INNER JOIN OSLP T2 ON T2.SlpCode=T1.SlpCode
LEFT OUTER JOIN RDR3 T3 ON T3.DocEntry=T1.DocEntry
WHERE T1.DocDate BETWEEN '1.1.17' AND '4.30.17'
AND T1.CANCELED='N' AND T1.U_StatusCancel='N'
GROUP BY T2.SlpName,T1.CardName, T1.DocDate) S
PIVOT (SUM(S.[Total]) FOR [month] IN ([1],[2],[3],[4])
) P Order By P.SRNAME, P.Customer
The logic that i was thinking was
SELECT SRNAMe, Customer,
ISNULL([1],0) as [Jan], column as jan-chrg,
ISNULL([2],0) as [Feb], column as feb-chrg,
ISNULL([3],0) as [Mar], column as mar-chrg,
ISNULL([4],0) as [Apr], column as apr-chrg
and i dont know the rest, maybe put those total charges inside pivot but, seems not gonna work.
please help, if you are getting what i want. Thanks
After meditating day and night, i finally found the answer my self. And hope this helps you guys as well(you know, for ideas).
SELECT SRNAMe, Customer,
ISNULL([1],0) as [Jan], ISNULL(jancharge,0) as [Charge],
ISNULL([2],0) as [Feb], ISNULL(febcharge,0) as [Charge],
ISNULL([3],0) as [Mar], ISNULL(marcharge,0) as [Charge],
ISNULL([4],0) as [Apr], ISNULL(jancharge,0) as [Charge]
FROM (SELECT T2.SlpName SRNAMe,T1.CARDNAME Customer, (SELECT TOP 1 T9.TotalSumSy FROM RDR3 T9 INNER JOIN ORDR T8 ON T8.DocEntry=T9.DocEntry WHERE MONTH(T8.DocDate)=1 AND T8.CardName=T1.CardName) jancharge,
(SELECT TOP 1 T9.TotalSumSy FROM RDR3 T9 INNER JOIN ORDR T8 ON T8.DocEntry=T9.DocEntry WHERE MONTH(T8.DocDate)=2 AND T8.CardName=T1.CardName) febcharge,
(SELECT TOP 1 T9.TotalSumSy FROM RDR3 T9 INNER JOIN ORDR T8 ON T8.DocEntry=T9.DocEntry WHERE MONTH(T8.DocDate)=3 AND T8.CardName=T1.CardName) marcharge,
(SELECT TOP 1 T9.TotalSumSy FROM RDR3 T9 INNER JOIN ORDR T8 ON T8.DocEntry=T9.DocEntry WHERE MONTH(T8.DocDate)=4 AND T8.CardName=T1.CardName) aprcharge, SUM(T1.DocTotal) as Total,MONTH(T1.Docdate) as [month]
FROM ORDR T1 INNER JOIN OSLP T2 ON T2.SlpCode=T1.SlpCode
LEFT OUTER JOIN RDR3 T3 ON T3.DocEntry=T1.DocEntry
WHERE T1.DocDate BETWEEN '1.1.17' AND '4.30.17'
AND T1.CANCELED='N' AND T1.U_StatusCancel='N'
GROUP BY T2.SlpName,T1.CardName, T1.DocDate) S
PIVOT (SUM(S.[Total]) FOR [month] IN ([1],[2],[3],[4])
) P Order By P.SRNAME, P.Customer
I'm used to make queries with sparql, but i have to do this one with mysql that i don't really know the syntax.
I have these three tables:
Products:
id o
1 p1
2 p2
Specification:
id o
3 sp1
4 sp2
Source:
id o
1 s1
3 s1
2 s2
4 s2
As we see, the products and the specifications can be connected with the source different ids, so i guess i have to make 2 selects with 2 inner joins between source > product and source > specification and an inner join between the 2 selects :
SELECT * FROM
(
SELECT pt.o as po, st.id as psID, st.o as pso
FROM source_test st
inner join products_test pt on st.id = pt.id
) x INNER JOIN
(
SELECT st2.o as spo, st1.id as spsID,st1.o as spso
FROM source_test st1
inner join specification_test st2 on st1.id =st2.id
) y
This gives:
po psID pso spo spsID spso
p1 1 s1 sp1 3 s1
p2 2 s2 sp1 3 s1
p1 1 s1 sp2 4 s2
p2 2 s2 sp2 4 s2
Now i need to filter product (po) and the specification (spo) that have the same source (pso),(spso)
I'm i on doing things the right way, what could be the continuation or a good query to get:
po spo spso
p1 sp1 s1
p2 sp1 s2
Thanks in advance.
select p.o, s.o, so.o
from products p
left join specification s
left join source so on p.id=s.id and p.id = so.id;
The only thing i had to do is to to filter y ON x.pso = y.spso
SELECT * FROM
(
SELECT product.o as po, source.s as psID, source.o as pso FROM source
inner join product
on source.s = product.s
) x INNER JOIN
(
SELECT specification.o as spo, source.s as spsID, source.o as spso FROM source
inner join specification
on source.s = specification.s
) y ON x.pso = y.spso
result:
po psID pso spo spsID spso
p1 1 s1 sp1 3 s1
p2 2 s2 sp2 4 s2
Add ON x.pso = y.spso to your query:
SELECT x.po, y.spo, y.spso
FROM
(
SELECT products_test.o as po, source_test.id as psID, source_test.o as pso FROM source_test
inner join products_test
on source_test.id = products_test.id
) x INNER JOIN
(
SELECT specification_test.o as spo, source_test.id as spsID,source_test.o as spso
FROM source_test
inner join specification_test on source_test.id =specification_test.id
) y
ON x.pso = y.spso
I'm not sure if what I'm looking to do is possible with a union, or if I need to use a nested query and join of some sort.
select c1,c2 from t1
union
select c1,c2 from t2
// with some sort of condition where t1.c1 = t2.c1
Example:
t1
| 100 | regular |
| 200 | regular |
| 300 | regular |
| 400 | regular |
t2
| 100 | summer |
| 200 | summer |
| 500 | summer |
| 600 | summer |
Desired Result
| 100 | regular |
| 100 | summer |
| 200 | regular |
| 200 | summer |
I've tried something like:
select * from (select * from t1) as q1
inner join
(select * from t2) as q2 on q1.c1 = q2.c1
But that joins the records into a single row like this:
| 100 | regular | 100 | summer |
| 200 | regular | 200 | summer |
Try:
select c1, c2
from t1
where c1 in (select c1 from t2)
union all
select c1, c2
from t2
where c1 in (select c1 from t1)
Based on edit, try the below:
MySQL doesn't have the WITH clause which would allow you to refer to your t1 and t2 subs multiple times. You might want to create both t1 and t2 as a view in your database so that you can refer to them as t1 and t2 multiple times throughout a single query.
Even still, the query below honestly looks very bad and could probably be optimized a lot if we knew your database structure. Ie. a list of the tables, all columns on each table and their data type, a few example rows from each, and your expected result.
For instance in your t1 sub you have an outer join with with the LESSON table, but then you have criteria in your WHERE clause (lesson.dayofweek >= 0) which would naturally not allow for nulls, effectively turning your outer join into an inner join. Also you have subqueries that only check for the existence of studentid using criteria that would suggest several tables used don't actually need to be used to produce your desired result. However without knowing your database structure and some example data with an expected result it's hard to advise further.
Even still, I believe the below will probably get you what you want, just not optimally.
select *
from (select distinct students.student_number as "StudentID",
concat(students.first_name, ' ', students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name, ' ', teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number = students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER = account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson.dayofweek >= 0 and
order by students.STUDENT_NUMBER) t1
where StudentID in
(select StudentID
from (select distinct students.student_number as "StudentID",
concat(students.first_name,
' ',
students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name,
' ',
teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number =
students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER =
account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson_summer.dayofweek >= 0
order by students.STUDENT_NUMBER) t2)
UNION ALL
select *
from (select distinct students.student_number as "StudentID",
concat(students.first_name, ' ', students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name, ' ', teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number = students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER = account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson_summer.dayofweek >= 0
order by students.STUDENT_NUMBER) x
where StudentID in
(select StudentID
from (select distinct students.student_number as "StudentID",
concat(students.first_name,
' ',
students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name,
' ',
teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number =
students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER =
account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson.dayofweek >= 0 and
order by students.STUDENT_NUMBER) x);
In order to compare values from two tables you need to do a join. The first way I see is to do 2 queries with inner join and union them:
select t1.* from t1
inner join t2 using (c1)
union
select t2.* from t1
inner join t2 using (c1)
However, we can do better: you can see that I use the exact same query up to which columns I select in the result set, that's a bit of a waste. If we could simply duplicate every records(1)? Well, we can:
select * from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
Now we have everything in double, with an extra column for parity, we just need to select either set of column on that:
-- broken query
select case parity when
0 then t1.*
1 then t2.*
end from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
Unfortunately, the case expression does not allow to return several columns, thus we need to include the test for all of them. In your case, one column is enough:
select c1, case parity when
0 then t1.c2
1 then t2.c2
end from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
order by c1
-- order by parity, c1
Use the commented out order by instead to get the result set for t1 first, an then t2.
Caveat: code untested.
(1) There's this feature called CTE in ANSI SQL (99 I think) which allows to factor out a common query and then reference it throughout the main query, but sadly mysql does not support it.
An UNION is okay.
You want to run the same join twice. Except that the first time over you get the left side, and the second time the right side.
SELECT t1.* FROM t1 JOIN t2 USING (c1)
UNION
SELECT t2.* FROM t1 JOIN t2 USING (c1)
Of course, if at all possible, you could run a single query and save the left side in memory, display the right side, then enqueue the saved left side at end. It needs much more memory than a cursor, but runs the query in half the time (something less actually, due to disk and resource caching).
See here the sample SQLFiddle.