T-SLQ Can you use aggregate in on clause? - sql

I have 2 call tables. Table 1 has call/client info. Table 2 has the call logs, what happened during call. I need to join table 2 to table 1 but only pull the 'Time' for the first phone. There are multiple 'Phone's in the call logs, need the time for the first one.
Table 1 Table 2 Goal
Call ID Client State Call ID Method Time Call ID Client State Time
1 John TX 1 Inbound 11:00 1 John TX 11:01
2 Mike CA 1 Phone 11:01 2 Mike CA 11:31
3 Susan NA 1 Answer 11:01 3 Susan NA ...
4 ... .... 1 Phone2 11:05 4
1 Call End 11:22 . etc
2 Inbound 11:30
2 Phone 11:31
Kinda want to do something like this.
SELECT *
FROM Table1 t1 on Table2 t2 = t1.call_id = t2.call_id and t2.Method like '%Phone%'
but this will pull all the phones times. Need MIN(phone). Can you use an aggregate in on clause?

No, you cannot use an aggregation in an on clause. Instead, use apply:
SELECT *
FROM Table1 t1 CROSS APPLY
(SELECT TOP (1) t2.*
FROM Table2 t2
WHERE t2.call_id = t1.call_id and
t2.Method like '%Phone%'
ORDER BY phone
) t2;

You can do it with ROW_NUMBER() window function:
select t1.*, t2.time
from table1 t1 inner join (
select *, row_number() over (partition by callid order by time) rn
from table2
where method like '%Phone%'
) t2 on t2.callid = t1.callid
where t2.rn = 1
or:
select t1.*,
(select min(time) from table2 where method like '%Phone%' and callid = t1.callid) time
from table1 t1

Related

SQL Access query VBA: how to gather the record that has the max nbr of subscriptions

This is my data:
id
key
nbr of subs
1
ABC
10
1
XXX
3
2
MNO
120
3
ABC
5
3
FGH
110
I need the key for the record (ID) that has the max nbr of subscriptions:
id
key
nbr of subs
1
ABC
10
2
MNO
120
3
FGH
110
I don't mind deleting the extra records, or electing the ones I need and insert them into other table. Any ideas?
SELECT P.Key, MAX(P.[Nbr of Subcriptions])
FROM P
GROUP BY P.Key;
Thank you very much
You need correlated subquery. Try below SQL-
SELECT t1.ID, t1.Key, t1.NBR FROM Table1 as t1
INNER JOIN (SELECT Table1.ID, Max(Table1.NBR) AS MaxOfNBR
FROM Table1 GROUP BY Table1.ID) as t2 ON (t1.NBR = t2.MaxOfNBR) AND (t1.ID = t2.ID);

How do I join two tables in SQL limiting the second table data depending on the first one?

I have two tables looking something like this:
IMP DATE CAT
A 03/03/2016 1
B 04/04/2016 1
C 09/09/2016 2
D 01/01/2017 1
E 02/02/2017 1
F 03/03/2017 2
G 04/04/2017 2
===================
EXP DATE CAT
H 01/01/2016 1
I 05/05/2016 1
J 07/07/2016 2
K 11/11/2016 2
L 01/01/2017 1
M 03/03/2017 1
N 04/04/2017 2
O 05/05/2017 2
I want to join the first table to the second one but limit the lines joined from the second table by the latest date on the first table (per category).
The result I'm looking for would be every row in both tables except Item "M" (because Cat 1 in Table 1 has a latest date of February) and Item "O" (because Cat 2 in Table 1 has a latest date of April).
I've tried conditionalds within a where clause in the 2nd table but haven't got far.
Is there a simple way to do this? Any help is appreciated. I'm using SQL Server 2008 by the way.
Your description of the problem is specifically about using join. That suggests a query like this:
select . . .
from (select t1.*, max(t1.date) over (partition by t1.cat) as maxdate
from table1 t1
) t1 join
table2 t2
on t1.cat = t2.cat and t2.date <= t1.maxdate;
Desire output and its format is still not clear.
are you looking for this ?
;With CTE as
(
select *, row_number()over(partition by cat order by DATEs desc) rn
from #table1
)
--select * from cte
--where rn=1
select * from cte t1
left join #table2 t2
on t1.CAT=t2.CAT and t2.DATEs<=t1.DATEs
where rn=1

Join table by id and nearest date for every date

I have 2 tables:
TABLE 1
id date_measured value 1
1 01/01/2017 5
1 02/20/2017 6
1 04/01/2017 5
2 03/02/2017 5
2 04/02/2017 3
TABLE 2
id date_measured value 2
1 01/06/2017 5
1 03/01/2017 6
2 02/01/2017 5
2 03/09/2017 7
2 04/05/2017 4
I want to join it such that each id matches and the closest date matches so:
id date_measured1 value 1 date_measured2 value 2
1 01/01/2017 5 01/06/2017 5
1 02/20/2017 6 03/01/2017 6
2 02/01/2017 5 02/01/2017 5
2 03/02/2017 5 03/09/2017 7
2 04/02/2017 3 04/05/2017 4
etc. IE for each id for each date measured take the closest measured date in the other table and make it a row. Something closeish to
SELECT *
FROM table1 a
INNER JOIN table2 b
ON a.id = b.id
AND <date from a is closest date from b>
But I have no idea how to do the second part. Any suggestions?
In standard SQL, you can get the date using a correlated subquery:
select t1.*,
(select t2.date_measured
from table2 t2
where t2.id = t1.id
order by abs(t2.date_measured - t1.date_measured) asc
fetch first 1 row only
) as t2_date_measured
from table1 t1;
You can then join back to table2 to get additional information from that row.
The above is generic SQL (not necessarily standard SQL). Date/time functions tend to be peculiar to each database; so - may not work for the difference. Not all databases support fetch first 1 row only, but almost all support some mechanism for doing the same thing.
If you have window functions use ROW_NUMBER():
SQL DEMO I use postgresql so date function may vary on your rdbms
WITH cte as (
SELECT *,
t1.id as t1_id,
t1.date_measured as t1_date,
t1.value1,
t2.id as t2_id,
t2.date_measured as t2_date,
t2.value2,
date_part('day', age(t1.date_measured, t2.date_measured)) as days,
ROW_NUMBER() OVER (PARTITION BY t1.id, t1.date_measured
ORDER BY abs(date_part('day', age(t1.date_measured, t2.date_measured)))
) as rn
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
)
SELECT *
FROM cte
WHERE rn = 1
ORDER BY t1_id, t1_date

MaxMin Function within Select Statement SQL 2012

I am having a few issues making a MAX function work within the select statement See example data below:
Table 1 Table 2
Visit_ID Car_ID Move_ID Visit_ID MoveStartDate MoveEndDate
A 1 1 A 25/07/2016 27/07/2016
B 2 2 A 28/07/2016 28/07/2016
C 1 3 B 19/07/2016 22/07/2016
D 3 4 D 28/06/2016 30/06/2016
I would like my select statement to pick the min start time and Max start time based on the Visit_ID so I would be expecting:
Result
Visit_ID Car_ID StartDate EndDate
A 1 25/07/2016 28/07/2016
B 2 19/07/2016 22/07/2016
So far I have tried I already have Inner Joins in my select statement:
,(MAX (EndDate) WHERE Visit.Visit_ID = Move.Visit_ID) AS End Date
I have looked at some other queries with a second select statement within the select so you end up with something like:
Select Visit_ID, Car_ID ,(Select MAX(EndDate) FULL OUTER JOIN Table 2 ON Table 1.Visit_ID = Table 2.Visit_ID Group By Table 1.Visit_ID) AS End Date
Hope I have provided enough info currently stumped.
If you also want Car_ID = 3 in the result:
select t1.Visit_ID, t1.Car_ID, MIN(MoveStartDate), MAX(MoveEndDate)
from table1 t1
join table2 t2 on t1.Visit_ID = t2.Visit_ID
group by t1.Visit_ID, t1.Car_ID
Returns:
SQL>select t1.Visit_ID, t1.Car_ID, MIN(MoveStartDate), MAX(MoveEndDate)
SQL&from table1 t1
SQL& join table2 t2 on t1.Visit_ID = t2.Visit_ID
SQL&group by t1.Visit_ID, t1.Car_ID;
visit_id car_id
======== =========== ==================== ====================
A 1 25/07/2016 28/07/2016
B 2 19/07/2016 22/07/2016
D 3 28/06/2016 30/06/2016
3 rows found
I did not check it but your can try this
WITH cte
AS
(select Move_ID,Visit_ID,min(MoveStartDate) AS mMS,MAX(MoveEndDate) AS mME
FROM Table_2
GROUP BY Move_ID,Visit_ID)
SELECT c.Move_ID,c.Visit_ID,T1.Car_ID,c.mMS,c.mME
FROM Table_1 as T1 JOIN cte as C
ON c.Visit_ID=T1.Visit_ID

MSSQL select single row with all references counted

I am attempting to do something using MSSQL that I believe is possible (easily) but I do not know how to vocalize the correct search string. I have the situation below.
Table A
UID | Value....
1 | a
2 | b
3 | c
Table B
PartTypes_uid_fk | Value....
1 | a
1 | b
1 | c
1 | d
1 | e
3 | 67
3 | 1354
I am attempting to get the following result, query Table A for all results {TableA.*} and on the same row result show the number of table b references {count TableB.tableA_fk}
What I have so far is the following.
SELECT DISTINCT t1.uid, CONVERT(varchar(MAX), t1.Name) AS Name, CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) OVER (Partition By t2.PartTypes_uid_fk) as Count
FROM [Table1] as t1 left outer join Table2 as t2 on t2.PartTypes_uid_fk=t1.uid;
This works for all of Table A records with an associated record in Table B but if there are 0 entries in Table B it won't work. The conversion of the varchars was required due to the fact they are ntext format and it was distinct.
Thank you for all your help in advance.
Stephen
Instead of running into problems with the GROUP BY on N/TEXT columns, and to run faster, you would want to pre-aggregate the B table and LEFT JOIN that against A.
select t1.*, ISNULL(t2.c, 0) AS CountOfB
from table1 t1
left join
(
select parttypes_uid_fk, count(*) c
from table2
group by parttypes_uid_fk
) t2 on t2.PartTypes_uid_fk=t1.uid
It's easier than that:
SELECT t1.uid, t1.Name, COUNT(*)
FROM [Table1] t1
LEFT JOIN [Table2] t2 ON t2.PartTypes_uid_fk = t1.uid
GROUP BY t1.uid, t1.Name
Your query should be
SELECT t1.uid,
CONVERT(varchar(MAX), t1.Name) AS Name,
CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) CountItems
FROM [Table1] as t1 left outer join Table2 as t2 on t1.uid = t2.PartTypes_uid_fk
GROUP BY uid, t1.name, t1.Description;