Joining Two Tables, getting Aggregate and unique value of one - sql-server

This may have been answered previously, but I'm having a difficult time describing my issue.
Let's say I have two tables
Table1
User, CalendarID
Joe 1
Joe 2
Joe 3
Sam 4
Bob 1
Jim 2
Jim 3
Table2
CalendarID, CalendarTime
1 2014-08-18 00:00:00.000
2 2015-01-19 00:00:00.000
3 2015-08-24 00:00:00.000
4 2016-01-18 00:00:00.000
What I would like to do is Join the two tables, only getting a single User Name, and Calendar ID based on what is this highest CalendarTime associated with that CalandarID.
So I would like the query to return
User CalendarID
Joe 3
Sam 4
Bob 1
Jim 3
The closest I've managed is
SELECT t1.User, MAX(t2.CalendarTIme) AS CalendarTime
FROM table1 t1
INNER JOIN table2 as t2
ON t1.CalendarID = t2.CalendarID
Group By t1.User
Which gets me the User and CalendarTime that I want, but not the Calendar ID, which is what I really want. Please help.

Closest to your script and pretty straightforward:
SELECT t1.User, t2.*
FROM table1 t1
INNER JOIN table2 as t2
ON t1.CalendarID = t2.CalendarID
WHERE NOT EXISTS
(
SELECT 1 FROM table1 t1_2
INNER JOIN table2 t2_2
ON t2_2.Calendar_ID = t1_2.Calendar_ID
WHERE t1_2.User = t1.User
AND t2_2.CalendarTime > t2.CalendarTime
)

This can be solved for the top N per group:
using top with ties with row_number():
select top 1 with ties
t1.User, t1.CalendarId, t2.CalendarTime
from table1 t1
inner join table2 as t2
on t1.Calendarid = t2.Calendarid
order by row_number() over (partition by t1.User order by t2.CalendarTime desc)
or using common table expression(or a derived table/subquery) with row_number()
;with cte as (
select t1.User, t1.CalendarId, t2.CalendarTime
, rn = row_number() over (partition by t1.User order by t2.CalendarTime desc)
from table1 t1
inner join table2 as t2
on t1.Calendarid = t2.Calendarid
)
select User, CalendarId, CalendarTime
from cte
where rn = 1

Related

Return sum using aggregate function in SQL Server

I have two tables.
Table1 has following data
Id1 Name Comments
--------------------
1 abc hgdhg
2 xyz mnoph
3 ysdfr jkljk
4 asdf iiuoo
5 pqrs liuoo
Table2 has following data
Id2 Id1 count date
-------------------------------
1 1 18 11/16/2005
2 1 1 11/15/2005
3 1 4 11/25/2005
4 2 4 11/22/2005
5 3 8 11/05/2005
6 3 3 11/30/2005
7 4 2 11/29/2005
8 3 0 11/04/2005
9 2 5 11/02/2005
10 3 9 11/22/2005
11 2 15 11/10/2005
12 5 12 11/19/2005
I want to return output as name, comments, sum of all count since 11/10/2005
I am trying the following query(with out date where condition)
select
Name, Comments, sum(count)
from
Table1 T1
join
Table2 T2 on T1.Id1 = T2.Id1
group by
ID1
But it is throwing error
Name is invalid in the select list because it is not contained in either an aggregate function or the Group by clause.
Can anyone help me with query (with the date where condition)? What's wrong with this?
Thanks in advance
You have to add any columns not contained in the aggregate function, and use where to filter the results:
select Name,
Comments,
sum(count)
from Table1 T1 join Table2 T2 on T1.Id1 = T2.Id1
where T2.[date] >= '11/10/2005'
group by Name, Comments
you can use below query
SELECT T1.Name ,
T1.Comments ,
SUM(T2.[count]) AS [count]
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Id1 = T2.Id1
WHERE CAST(T2.[date] AS DATE) >= CAST('11/10/2005' AS DATE)
GROUP BY T1.Name ,
T1.Comments
Every column in a select statement without an aggregate function needs to be in the group by sentence too to prevent aggregate errors, about limiting the date, use where clause to define the condition, like shows ahead.
select
Name, Comments, sum(count)
from
Table1 T1
join
Table2 T2 on T1.Id1 = T2.Id1
where
date >= '2005-11-10 00:00:00'
group by
Name, Comments

T-SQL: Join three tables and limit to earliest encounter

I'm fairly new to sql and have sunk a whole day into trying to figure out how to do the following. I have 3 tables that look something like this:
Table 1
customer_id department_id start_dts
1 2 2011-07-23 14:30:00
3 1 2011-07-24 10:15:00
3 1 2011-08-18 11:14:00
2 3 2012-05-04 05:45:00
1 3 2010-06-09 15:20:00
Table 2
department_id deparment_nm
1 a
2 b
3 c
Table 3
customer_id customer_nm
1 betty
2 fred
3 dino
I want to generate a list of the earliest encounter for each department and the associated customer name for the encounter such that it would look something like this (order of the dept doesn't matter):
department_nm customer_nm start_dts
a dino 2011-07-24 10:15:00
b betty 2011-07-23 14:30:00
c betty 2010-06-09 15:20:00
I first attempted to join table 2 on table 1 by department_id then inner joining table 3 on customer_id and using the min function for start_dts under the select statement, but that gives me each customers first encounter in each department. I then tried various iterations of nested joins and attempted to use an over/partition clause to get what I want, but I don't think I'm understanding that concept correctly. Any insight is very appreciated.
;with cte as (
select dept_nm, cust_nm, row_number() over (partition by t1.dept_id order by start_dts) rn, start_dts from table1 t1
left join table2 t2
on t1.dept_id = t2.dept_id
left join table3 t3
on t1.cust_id = t3.cust_id
) select * from cte where rn=1
Not sure i understood your requirement correctly.. but looks you are trying something like this...
Pretty sparse on actual details but something like this is what you are looking for. This has been asked and answered hundreds and hundreds of times.
select department_nm
, customer_nm
, start_dts
from
(
select department_nm
, customer_nm
, start_dts
, ROW_NUMBER() over(partition by t1.customer_id, t1.department_id order by t1.start_dts desc) as RowNum
from table1 t1
join table2 t2 on t2.department_id = t1.department_id
join table3 t3 on t3.customer_id = t1.customer_id
) x
where x.RowNum = 1
I feel like CTEs and Window functions are overkill for something like this. The following should work, if I understood correctly.
SELECT department_nm, customer_nm, MIN(start_dts) AS [start_dts]
FROM
(
SELECT department_nm, customer_nm, start_dts
FROM Table1 t1
JOIN Table2 t2 ON t1.department_id = t2.department_id
JOIN Table3 t3 ON t1.customer_id = t2.customer_id
) x
GROUP BY department_nm, customer_nm

How to use SQL(Max) function

I have 2 tables
Table 1:
id name adress
1 John New York
2 Jane London`
... and so on
Table 2:
id fila date
1 43 01/01/2010
1 39 10/01/2011
1 55 23/12/2012
2 10 01/01/2008
2 15 02/02/2010`
.... and so on
I want to get data like this
id fila name adress date
-----------------------------------------
1 55 John New York 23/12/2012
2 15 Jane London 02/02/2010
..... and so on.
Thanks
ok. what you are really looking for is "What is the latest date in table2 for each of my rows in Table1". So to answer the question:
select *
From Table1
inner join (
select id, max(fila) as maxfila
from Table2
group by id
) as maxdates
on Table1.id = maxdates.id
inner join Table2 on Table2.id = maxdates.id AND Table2.fila = maxdates.maxfila
Try this:
;with cte as
(select id, max(fila) maxfila
from table2
group by id)
select t1.id, t1.name, t1.address, t2.fila, t2.date
from table1 t1
left join table2 t2 on t1.id = t2.id
inner join cte c on t1.id = c.id
where t2.fila = c.maxfila
Try this
Select t1.id, t1.name, t1.address, t2.maxfila
from table1 t1
left outer join
(select id, max(fila) maxfila
from table2
group by id) t2
select t1.id, t1.name t1.address, max(t2.fila),
(select top 1 date from table2 order by fila desc where table2.id = t1.id)
from table1 t1 inner join
table2 t2 on t1.id = t2.id

How to get values from two tables in SQL Server?

I have 2 tables in SQL Server 2008 and I want to get the details from those 2 tables using join.
T-1 : vwHardwareConsolidate
|ID|||Qty|Type|Task_Id|
T-2 :
|MasterID|Task_Id|Act_Qty|
I want to get id, task_name, sum(qty), task_id from T1 and Masterid, Act_Qty from T2
I have tried this query
select
ID as MasterID, Task_id, Task_Name as Items,
SUM(Qty) as Req_Qty, 0 as Act_Qty
from
vwHardwareConsolidate
where
type = 'Reqrd' and ID = '21'
Group by
Task_Name,id,Task_id
union
(select
m.MasterID, m.Task_Id, vw.Task_Name as Items, 0 as Req_Qty, m.Act_Qty
from
vwHardwareConsolidate vw
Right join
(select
MasterID, m.Task_Id, 0 as Req_Qty, sum(Act_qty) as Act_Qty
from
tbl_MaterialDistribution_Detail m
where
MasterID = '21'
group by
m.Task_Id, MasterID) as m on m.Task_Id = vw.Task_id)
vwHardwareConsolidate
ID Site_name Qty Task_Name Type
1 CITY 1 A16Port_Switch Reqrd
1 CITY 1 Digital_Camera Reqrd
1 CITY 1 Electronic_Pen Reqrd
tbl_MaterialDistribution_Detail:
MasterID|TaskId|Act_qty
7 31 1
2 32 1
12 39 3
Please try this
select t1.ID, t1.Task_Name,Sum(t1.Qty) as Qty,t1.Task_Id,t2.MasterID,t2.Act_Qty
from vwHardwareConsolidate as t1
left outer join table2 as t2
on t2.Task_ID=t1.Task_ID
Group By t1.ID, t1.Site_name, t1.Task_Name,t1.Qty,t1.Type,t1.Task_Id,t2.MasterID,t2.Act_Qty
May this will help you.
SQL Fiddle Demo
You can use
SELECT T1.Id, T1.SiteName,T1.TaskName,T.Type,T2.Act_Qty,T2.MasterID,T2.Task_Id,SUM(Qty)AS
Qty FROM T1 INNER JOIN T2 ON T1.Task_Id=T2=Task_Id GROUP BY T1.Id, T1.SiteName,
T1.TaskName,T.Type,T2.Act_Qty,T2.MasterID,T2.Task_Id
something this way,
select a.id,a.Task_Name,b.qty,c.Act_Qty from vwHardwareConsolidate a inner join
tbl_MaterialDistribution_Detail c on a.id=c.task_id
inner join
(slect id,sum(qty)qty from vwHardwareConsolidate group by id)b
on a.id=b.id

Limited T-SQL Join

This should be simple enough, but somehow my brain stopped working.
I have two related tables:
Table 1:
ID (PK), Value1
Table 2:
BatchID, Table1ID (FK to Table 1 ID), Value2
Example data:
Table 1:
ID Value1
1 A
2 B
Table 2:
BatchID Table1ID Value2
1 1 100
2 1 101
3 1 102
1 2 200
2 2 201
Now, for each record in Table 1, I'd like to do a matching record on Table 2, but only the most recent one (batch ID is sequential). Result for the above example would be:
Table1.ID Table1.Value1 Table2.Value2
1 A 102
2 B 201
The problem is simple, how to limit join result with Table2. There were similar questions on SO, but can't find anything like mine. Here's one on MySQL that looks similar:
LIMITing an SQL JOIN
I'm open to any approach, although speed is still the main priority since it will be a big dataset.
WITH Latest AS (
SELECT Table1ID
,MAX(BatchID) AS BatchID
FROM Table2
GROUP BY Table1ID
)
SELECT *
FROM Table1
INNER JOIN Latest
ON Latest.Table1ID = Table1.ID
INNER JOIN Table2
ON Table2.BatchID = Latest.BatchID
SELECT id, value1, value2
FROM (
SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn
FROM table1 t1
JOIN table2 t2
ON t2.table1id = t1.id
) q
WHERE rn = 1
Try
select t1.*,t2.Value2
from(
select Table1ID,max(Value2) as Value2
from [Table 2]
group by Table1ID) t2
join [Table 1] t1 on t2.Table1ID = t1.id
Either GROUP BY or WHERE clause that filters on the most recent:
SELECT * FROM Table1 a
INNER JOIN Table2 b ON (a.id = b.Table1ID)
WHERE NOT EXISTS(
SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID
)

Resources