sql server - join 2 tables based on earliest date in 2nd table - sql

I'm looking for query advise to gather data on the following.
Table 1 'Case' - contains columns: Id, Customer, Product, Reported Date
Table 2 'Activity - contains columns: Case Id, Date Created, Created By
There can be many activities linked to the same case. What I'd like to do is write a query to return the following.
Case.Id, Case.Customer, Case.Product, Case.ReportedDate,
Activity.DateCreated, Activity.CreatedBy,
datediff(hour, Case.ReportedDate, Activity.DateCreated)
BUT ONLY for the activity with the earliest date. Basically showing the time difference between when the case was first created and the first activity was created.
I'd really appreciate any advice on how to accomplish this join. I tried a few things but it ended returning multiple rows per case. Thanks very much!

Try this...
SELECT C.ID
,C.Customer
,C.Product
,C.ReportedDate
,DATEDIFF(HOUR, C.ReportedDate, A.DateCreated) AS [TimePassed]
,A.CreatedBy
FROM [Case] C INNER JOIN
(SELECT *,
ROW_NUMBER() OVER (PARTITION BY CaseId ORDER BY DateCreated ASC) AS rn
FROM [Activity]) A
ON C.ID = A.CaseId
WHERE A.rn = 1

Related

select rows in sql with latest date from 3 tables in each group

I'm creating PREDICATE system for my application.
Please see image that I already
I have a question how can I select rows in SQL with latest date "Taken On" column tables for each "QuizESId" columns, before that I am understand how to select it but it only using one table, I learn from this
select rows in sql with latest date for each ID repeated multiple times
Here is what I have already tried
SELECT tt.*
FROM myTable tt
INNER JOIN
(SELECT ID, MAX(Date) AS MaxDateTime
FROM myTable
GROUP BY ID) groupedtt ON tt.ID = groupedtt.ID
AND tt.Date = groupedtt.MaxDateTime
What I am confused about here is how can I select from 3 tables, I hope you can guide me, of course I need a solution with good query and efficient performance.
Thanks
This is for SQL Server (you didn't specify exactly what RDBMS you're using):
if you want to get the "latest row for each QuizId" - this sounds like you need a CTE (Common Table Expression) with a ROW_NUMBER() value - something like this (updated: you obviously want to "partition" not just by QuizId, but also by UserName):
WITH BaseData AS
(
SELECT
mAttempt.Id AS Id,
mAttempt.QuizModelId AS QuizId,
mAttempt.StartedAt AS StartsOn,
mUser.UserName,
mDetail.Score AS Score,
RowNum = ROW_NUMBER() OVER (PARTITION BY mAttempt.QuizModelId, mUser.UserName
ORDER BY mAttempt.TakenOn DESC)
FROM
UserQuizAttemptModels mAttempt
INNER JOIN
AspNetUsers mUser ON mAttempt.UserId = muser.Id
INNER JOIN
QuizAttemptDetailModels mDetail ON mDetail.UserQuizAttemptModelId = mAttempt.Id
)
SELECT *
FROM BaseData
WHERE QuizId = 10053
AND RowNum = 1
The BaseData CTE basically selects the data (as you did) - but it also adds a ROW_NUMBER() column. This will "partition" your data into groups of data - based on the QuizModelId - and it will number all the rows inside each data group, starting at 1, and ordered by the second condition - the ORDER BY clause. You said you want to order by "Taken On" date - but there's no such date visible in your query - so I just guessed it might be on the UserQuizAttemptModels table - change and adapt as needed.
Now you can select from that CTE with your original WHERE condition - and you specify, that you want only the first row for each data group (for each "QuizId") - the one with the most recent "Taken On" date value.

how to get latest date column records when result should be filtered with unique column name in sql?

I have table as below:
I want write a sql query to get output as below:
the query should select all the records from the table but, when multiple records have same Id column value then it should take only one record having latest Date.
E.g., Here Rudolf id 1211 is present three times in input---in output only one Rudolf record having date 06-12-2010 is selected. same thing with James.
I tried to write a query but it was not succssful. So, please help me to form a query string in sql.
Thanks in advance
You can partition your data over Date Desc and get the first row of each partition
SELECT A.Id, A.Name, A.Place, A.Date FROM (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date DESC) AS rn
FROM [Table]
) A WHERE A.rn = 1
you can use WITH TIES
select top 1 PERCENT WITH TIES * from t
order by (row_number() over(partition by id order by date desc))
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=280b7412b5c0c04c208f2914b44c7ce3
As i can see from your example, duplicate rows differ only in Date. If it's a case, then simple GROUP BY with MAX aggregate function will do the job for you.
SELECT Id, Name, Place, MAX(Date)
FROM [TABLE_NAME]
GROUP BY Id, Name, Place
Here is working example: http://sqlfiddle.com/#!18/7025e/2

Table inner join itself

I have a table with 3 columns (code, state, date), it records the history of a code state, each code may have changed state multiple times.
I want to show the last state of each code what I did was like this
SELECT code,MAX(date), ....
FROM table
GROUP BY code.
I don't know what to put exactly to get the state. I tried to just put state so it gets the state corresponding to the combination of code,max(date) but it gives me the error of not in aggregate function.
thank you in advance for your help.
If I understand you have data such as
CODE State Date
1 IL 1/1/2016
1 IA 1/1/2017
1 AL 1/1/2015
and you want to see in your results
1 IA 1/1/2017
using a window function and a common table expression (with): we assign a row number to each code based on the date in descending order and return only the first row for each.
With CTE AS (SELECT code
, date
, state
, Row_number() over (partition by code order by date desc) RN
FROM table )
SELECT Code, Date, State
FROM CTE
WHERE RN =1
Using a subquery: (we get the max date for each code and then join back to the base set to limit the rows returned.
SELECT A.code, A.date, A.state
FROM table A
INNER JOIN (SELECT max(date) mdate, code
FROM table
GROUP BY code) B
on A.Code = B.Code
and A.Date = B.MDate
The later query was used when/if window functions are not available. The modern method of solving your question is using the first approach.
In essence what the 1st query does is assign the # 1 to x for each code based on the date descending. So the max date gets a RN of 1 for each code. Thus when we say where RN = 1 we only return codes/states/records having max dates for the code in question. We use a with statement because we need the RN to materialize (actually get generated in memory) so that we can then limit by it in the second part of the with (common table expression) query.
If you're doing an aggregate, like MAX(), then all other non-aggregate columns that are in your select, need to also be in your GROUP BY. That's why you're getting the error when you add state to only the select. If you add it to the select and group by it, you'll get your results:
SELECT State, Code, MAX(Date)
FROM table
GROUP BY State, Code
If you want to user inner join like you mention in your post Inner join back to itself with matching code and date
SELECT *
FROM table t1
INNER JOIN (SELECT code,MAX(date)
FROM table
GROUP BY code) codeWithLatestDate ON t1.code = codeWithLatestDate.code AND t1.date = codeWithLatestDate.dat3
However I would suggest add state to your GROUP BY clause and SELECT cluase
SELECT code,MAX(date),state
FROM table
GROUP BY code, state
Youn can do it with a join to itself
SELECT State,Code,Date
FROM table t
JOIN (
SELECT Code, MAX(Date) as Date
FROM table
GROUP BY Code) t1 on t1.Code= t.Code and t.Date=t1.Date

SQL Server : get latest date from 2 tables

I have two tables P and G and want to write a query that will get the latest date from table G and will not pull in duplicate client IDs:
Table P
Table G
I want to get this result from the query:
So far I have joined the tables, but unable get the result intended.
Any help would be appreciated.
Not sure how your tables are related other than your column ClientID, but you would want to join the two tables on those columns:
select p.clientid,
max(g.created_on) latest_created_on,
max(p.info) as info
from tableP p
left join tableG g on p.ClientID = g.ClientID
group by p.clientid;
SQL Fiddle Demo
You can use OVER PARTITION to take the record with the most recent date for each ClientID.
In this case, I would write:
SELECT g.ClientID,
g.created_on,
g.INFO
FROM (
SELECT ClientID
created_on,
INFO,
row_number() OVER ( PARTITION BY ClientID ORDER BY created_on DESC) AS RowNum
FROM Table_G
) AS g
WHERE g.RowNum = 1
The subquery creates a table with all the columns you want, and the row_number() function assigns each record a row_number. PARTITION BY says what to group by, and ORDER BY says how to sort within that partition.
In this case, you want the record with the most recent date for each ClientID. We group by ClientID, sort by date to assign row numbers, and then in the main query, we select only the first row in each group, using WHERE g.RowNum = 1
This is a guide for PostreSQL, but it's helped me understand OVER PARTITION.

SQL Retrieve First Matching row

I have a database which has two tables. A Call_Info table which holds details about incoming / outgoing calls and has a unique ID named Call_ID. I have a second table which is linked and called the After_Call_Work table.
Each call will have only one After Call Work Record. The dataset is a bit messed up and for the same call there are occasionaly 3 or 4 after call work records. How can I when doing queries just retrieve the earliest After Call Work Record for that particular call ignoring the rest? I imagined using SQL function First_Value but it doesn't seem to be the right one.
Using Microsoft SQL Server 2012.
Any ideas?
You should be able to use select top, something like this:
SELECT TOP 1
FROM call_info ci JOIN after_call_work acw ON ci.call_id=acw.call_id
ORDER BY acw.work_time DESC
WHERE ci.call_id=<your_call_id>
This can be achieved by taking advantage of Window Function
WITH call_List
AS
(
SELECT Call_ID, OtherColumns, DateColumn,
ROW_NUMBER() OVER (PARTITION BY Call_ID ORDER BY DateColumn ASC) rn
FROM After_Call_Work
)
SELECT a.*, b.OtherColumns, b.DateColumn
FROM Call_Info a
INNER JOIN call_List b
ON a.Call_ID = b.Call_ID
WHERE b.rn = 1
SQLFiddle Demo
TSQL Ranking Function
WITH g AS (SELECT ROW_NUMBER() OVER (PARTITION BY callid
ORDER BY date ASC) AS row,* from after_call_work
select * from call_info cinfo inner join g on
cinfo.callid = g.callid and g.row=1