How to select the most recent data from SQL joining 3 tables? - sql

I have 3 tables. I need to join the (AGENT table) from (DATA table) by column RANKDATA. There may be multiple entries in the DATA table. I need to select the most recent based on the DATE, then get the CODE_ID and join in CODE table.
Here's my code. I tried to use Max(D.DATE) but I got an error. My only problem, I don't know how to group it by the most recent date.
select A.ID, A.NAME, C.CODE_NAME, D.DATE
from Agent A
JOIN Data D ON A.RANKDATA = D.RANKDATA
JOIN CODE C ON D.CODE_ID = C.CODE_ID
output

I'm not quite clear on what your results are supposed to be from your image, bu t an alternative to doing this with a group by might be to use row_number. row_number basically projects a column with an incrementing integer (1,2,3,...n) over your rows. You can "partition" the function in the same way you would a group by. In this case, I partitioned it by a.RankData, but that was sort of a guess at what you wanted. The order by defines in what order the row numbering will appear. In this case, I've ordered it by d.[date] descending so the most recent date for every a.RankData will be the number 1. Finally, I turn all that into a subquery so I can put the new column in a where clause and just skim off those where RID = 1 (i.e the date is the max date).
select *
from (select
RID = row_number() over(partition by a.RankData order by d.[date] desc),
A.ID,
A.NAME,
C.CODE_NAME,
D.DATE
from Agent A
inner join [Data] D
on A.RANKDATA = D.RANKDATA
inner join CODE C
on D.CODE_ID = C.CODE_ID) a
where a.RID = 1

You could try using a CROSS APPLY, as an additional option.
SELECT A.ID, A.NAME, T.CODE_NAME, T.DATE
FROM Agent A
CROSS APPLY
(SELECT TOP 1 C.CODE_NAME, D.DATE
FROM
Data D JOIN CODE C ON D.CODE_ID = C.CODE_ID
WHERE A.RANKDATA = D.RANKDATA
ORDER BY D.DATE DESC) T
An image helps to visualize. But if you need time from others to help you, it would definitely be useful if you include a simple script to create your test data:
Something like this:
CREATE TABLE Agent (ID INT, NAME VARCHAR(30) ,RANKDATA INT)
INSERT INTO Agent
VALUES (1,'Mark',12), (2,'Joe',13), (3,'Steve',11), (4,'Sam',10)
CREATE TABLE DATA (ID int, RANKDATA int, CODE_ID VARCHAR(2), DATE datetime)
INSERT INTO DATA
VALUES (1,12,'01','20170901 2:30'), (2,13,'02','20170901 6:30'),
(3,11,'03','20170901 4:30'), (4,10,'02','20170901 1:30'),
(5,10,'03','20170901 2:50'), (6,12,'02','20170901 5:30')
CREATE TABLE CODE(ID int, CODE_ID varchar(2), CODE_NAME Varchar(15))
INSERT INTO CODE
VALUES (1,'01','RANK 1'), (2,'02','RANK 2'), (3,'03','RANK 3')

Related

look up dynamic value from range in another table

I have 2 tables. The first one is a detail table with years and actual limit values. The second table has max control limits but only for certain years.
Table 1 & 2
What I want to do is list all of the detail records but pull in the values of the control limits if the year is less than the next one listed in the control table.
Desired results:
results
I have tried this query but it duplicates 2015, 2016 and 2017.
SELECT d.id, d.yeard, d.value, c.Column1
FROM detailTbl d
RIGHT OUTER JOIN controlTbl c ON d.dated <= c.datec
You may use Row_Number() function as the following to remove duplicates:
with cte as
(
Select D.id,D.yeard,D.val, C.limitVal,
row_number() over (partition by D.id order by C.yeard desc) as rn from
detailTbl D left join controlTbl C
on D.yeard>=C.yeard
)
Select B.id,B.yeard,B.val,B.limitVal from
cte B where B.rn=1 order by B.id
See a demo on MySQL 8.0 from here.

SQL Cross Apply with three tables

I am trying to combine 3 tables using Cross Apply in a time-efficient manor. I can get the results that I want, but the run time is too great. The three tables are:
-CUSTOMERS, which has the columns CustomerId(primary key) and CurrentSetType
-HISTORY, which has the columns CustomerId(foreign key), SetType, and TimeStamp
-UPDATELIST, which has the column CustomerId
My goal is to find the most recent SetType from HISTORY for each CustomerId in UPDATELIST that is different from the CurrentSetType (this is part of a glorified 'undo' button). I believe my problem is that the CUSTOMERS and HISTORY tables are enormous, and I don't think I'm getting them paired down to the smaller UPDATELIST before doing a cross apply on the entire thing. My current query is this:
DECLARE #UPDATELIST TABLE (Identifier INT NOT NULL PRIMARY KEY);
INSERT INTO #UPDATELIST (Identifier) VALUES (#####); -- a few hundred lines of this
SELECT CustomerId, ITEM.SetType
FROM CUSTOMERS
CROSS APPLY
(SELECT TOP 1 SetType FROM HISTORY
WHERE HISTORY.CustomerId IN (SELECT Identifier FROM #UPDATELIST)
AND HISTORY.CustomerId = CUSTOMERS.CustomerId
AND HISTORY.SetType != CUSTOMERS.CurrentSetType ORDER BY TimeStamp DESC) AS ITEM
What is the most efficient query for this?
EDIT: I am using MSDN SQL version 12.0.5532
My first thought would be something like this:
SELECT
CustomerID
, SetType
FROM
(
SELECT
C.CustomerID
, H.SetType
, ROW_NUMBER() OVER (PARTITION BY C.CustomerID ORDER BY H.TimeStamp DESC) R
FROM
CUSTOMERS C
JOIN UPDATELIST U ON U.CustomerId = C.CustomerId
JOIN HISTORY H ON
H.CustomerId = C.CustomerId
AND H.SetType <> C.CurrentSetType
) Q
WHERE R = 1
How does that work?

Why is my Left Not pulling all the dates even though they exist on the other table SQL

I have a table without dates and wish to join on the table with dates.I am doing a left join on id and bn_number. The id can have more than one dates , i obviously want the latest date from the other tables as it has more than one date for each id. i am not sure how to get all the dates at least then i can be able to choose the latest one.
select Reg_Property_id,a.Bnd_nbr,account_balance,abs(account_balanc‌​e) as Bond_Balance,a.Bnd_regDate
into #Jan2014ValidFin
from #Jan2014Valid aa
left join Pr_analytics..bond a
on aa.Reg_Property_id=a.Prop_id
and aa.bnd_nbr=a.Bnd_nbr
where aa.reg_property_id is not null
SQL
Please assist.
Use the ROW_NUMBER() window function to get the most recent date:
SELECT c.*
FROM (
SELECT a.cols, b.cols, ROW_NUMBER() OVER (PARTITION BY b.colID1,b.colID2 ORDER BY b.theDate DESC) AS rn
FROM a
LEFT OUTER JOIN b ON a.col1 = b.col1
AND a.col2 = b.col2
) c
WHERE c.rn = 1
A simple group by should do the trick:
SELECT
Reg_Property_id -- What table is this from?
,a.Bnd_nbr
,account_balance -- What table is this from?
,abs(account_balance) as Bond_Balance -- What table is this from?
,max(a.Bnd_regDate) as Bnd_regDate
into #Jan2014ValidFin
from #Jan2014Valid aa
left join Pr_analytics..bond a
on aa.Reg_Property_id = a.Prop_id
and aa.bnd_nbr = a.Bnd_nbr
where aa.reg_property_id is not null
group by
Reg_Property_id
,a.Bnd_nbr
,account_balance
,abs(account_balance)
Note that if there are no dates (a.Bnd_regDate), you will get NULL
Note also that if any of the values marked "what table is this from" are found in #Jan2014Valid, you will need to either aggregate them (max, sum, etc.) or include them in the group by clause--I can't tell which, from the information provided.

How to group my table for latest date and ID?

I have a table like this:
I need group this table latest date for every ID.
I mean, I want to get last row every ID. Here is my query:
SELECT DISTINCT ch.Date,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, [Date] from tblCommonHistory ) ch
ON ch.TableIDentity = rk.ID order by ID
How can I do what I want?
EDIT: This query worked for me:
SELECT DISTINCT ch.dt,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, max([Date]) as dt from tblCommonHistory group by TableIdentity) ch ON ch.TableIDentity = rk.ID order by ID
Just use aggregation:
select TableIdentity, max([date])
from tblCommonHistory
group by TableIdentity;
Your question only mentions one table. Your query has two; I don't understand the discrepancy.
It's strange that you have duplicated TableIdentity in tblCommonHistory, but otherwise you should not be getting multiple dates for the same ID from your query.
And also, the only reason to join the 2 tables seems to be that you need to skip those ID that are not present in the tblrisk (is it what you need to do?)
In that case, I'd suggest
SELECT max(ch.Date) AS [Date],ID FROM dbo.tblrisk AS rk
inner join tblCommonHistory AS ch ON ch.TableIDentity = rk.ID
group by ID order by ID

SQL Inner Join using Distinct and Order by Desc

table a.
Table b . I have two tables. Table A has over 8000+ records and continues to grow with time.
Table B has only 5 or so records and grows rarely but does grow sometimes.
I want to query Table A's last records where the Id for Table A matches for Table B. The problem is; I am getting all the rows from Table A. I just need the ones where Table A and B match once. These are unique Id's when a new row is inserted into table B and never get repeated.
Any help is most appreciated.
SELECT a.nshift,
a.loeeworkcellid,
b.loeeconfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM oeeworkcell a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
ORDER BY a.loeeworkcellid DESC
I am assuming you want to get the only the lastest (as you said) row from the TableA but JOIN giving you all the rows.You can use the Row_Number() to get the rownumber and then apply the join and filter it with the Where clause to select only the first row from the JOIN. So what you can try as below,
;WITH CTE
AS
(
SELECT * , ROW_NUMBER() OVER(PARTITION BY loeeconfigworkcellid ORDER BY loeeworkcellid desc) AS Rn
FROM oeeworkcell
)
SELECT a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM CTE a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
WHERE
a.Rn = 1
You need to group by your data and select only the data having the condition with min id.
SELECT a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM oeeworkcell a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
group by
a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
having a.loeeworkcellid = min(a.loeeworkcellid)