insert into temp table using Cross Apply? - sql

I want to create a temp table and insert values based on the select. The query doesn't execute, What am i missing ? I eventually want to loop thru the temp table
Create Table #temp (ID varchar(25),Source_Id varchar(25),Processed varchar(25), Status varchar(25),Time_Interval_Min varchar(25))
Insert into #temp
Select t.*
From
(SELECT DISTINCT source_id
FROM Activity_WorkLoad) t1
CROSS APPLY
(
SELECT TOP 1
aw.ID,
Source_Id
,Processed
,Status
,Time_Interval_Min
FROM [dbSDS].[dbo].[Activity_WorkLoad] aw
JOIN [dbSDS].[dbo].[SDA_Schedule_Time] st ON aw.SDA_Resource_ID = st.ID
WHERE aw.Source_Id = t1.Source_Id AND aw.Status = 'Queued'
ORDER BY Processed DESC
)t

When you cross apply, you still need an alias:
Insert into #temp (id, source_id, processed, status, time_interval_min)
Select tt.*
From (SELECT DISTINCT source_id
FROM Activity_WorkLoad
) t CROSS APPLY
(SELECT TOP 1 aw.ID, Source_Id, Processed, Status, Time_Interval_Min
FROM [dbSDS].[dbo].[Activity_WorkLoad] aw JOIN
[dbSDS].[dbo].[SDA_Schedule_Time] st
ON aw.SDA_Resource_ID = st.ID
WHERE aw.Source_Id = t.Source_Id AND aw.Status = 'Queued'
ORDER BY Processed DESC
) tt;
I also assume that you want results from the second subquery, not the first, because the first does not have enough columns.

Related

Query to pull the data from 3 tables based on latest load date and HashKey

I am trying write a SQL query to pull the data from 3 tables using JOINS on basis of common HashKey and I want to take all the updated records from 3rd table based on the load date(last increment/recent records) using SQL.
I have tried below SQL query but I am not able to get the recent record from third table.
SELECT
tab1.TennisID
tab1.TennisHashKey
tab3.LoadDate
tab2.TennisType
tab3.Clicks
tab3.Hit
tab3.Likes
fROM table1 tab1
LEFT JOIN table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
LEFT JOIN (SELECT * FROM Table3 WHERE LoadDate = (SELECT TOP 1 LoadDate FROM Table 3 ORDER BY LoadDate Desc)) tab3
ON tab2.TennisHashKey = tab3.TennishHashKey
I have matching number of records in Table 1 and Table 2, but there are multiple rows for same hashkey in Table3 based on loadDate.
Please provide your suggestion on this.
Thanks
Use ROW_NUMBER() to join only the most recent row from Table3.
SELECT
tab1.TennisID
, tab1.TennisHashKey
, tab3.LoadDate
, tab2.TennisType
, tab3.Clicks
, tab3.Hit
, tab3.Likes
FROM table1 tab1
LEFT JOIN table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
LEFT JOIN (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY TennisHashKey ORDER BY LoadDate DESC) rn
FROM Table3
) tab3
ON tab2.TennisHashKey = tab3.TennishHashKey
AND rn = 1;
Another approach: you can use OUTER APPLY and get latest row and select it.
declare #table1 table(tennisid char(1), tennishashkey char(4),loaddate date)
declare #table2 table(tennishashkey char(4),tennistype char(10), loaddate date)
declare #table3 table(tennishashkey char(4),loaddate date,clicks int, hit int, likes int)
insert into #table1 values('A','A001','2020-01-01')
insert into #table2 values('A001','grass','2020-01-01')
insert into #table3 values('A001','2020-01-01',0,0,0),('A001','2020-01-01',1,1,1);
SELECT
tab1.TennisID
, tab1.TennisHashKey
, tab3.LoadDate
, tab2.TennisType
, tab3.Clicks
, tab3.Hit
, tab3.Likes
FROM #table1 tab1
LEFT JOIN #table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
OUTER APPLY (
SELECT TOP 1 *
FROM #Table3 as tab3
where tab3.tennishashkey = tab1.tennishashkey
order by loaddate desc
) tab3
TennisID
TennisHashKey
LoadDate
TennisType
Clicks
Hit
Likes
A
A001
2020-01-01
grass
1
1
1

SQL Case Condition On Inner Join

I am currently trying to join a table to itself to check if for one email there exist two or more Ids.
I am trying to join my table with itself on its email. I then wanted to query my table with a case condition saying if the count of the email in the nested query > 1 then select the latest modified record in the outer table.
SELECT *
FROM table1 <-- outer table
WHERE email IN
(SELECT email, COUNT(*)
FROM table1 as src
INNER JOIN table1 ON src.Email = table1.Email AND src.Id = table1.id
GROUP BY src.Email)
How can I write a query to say if the count for the given email is greater than 1 then select the latest record from the outer table?
Why would you go through all that trouble? How about just selecting the last modified record:
select t1.*
from table1 t1
where t1.modified_dt = (select max(tt1.modified_dt)
from table1 tt1
where tt1.email = t1.email
);
Another way to do it using window functions:
DECLARE #Tab TABLE (ID INT, Email VARCHAR(100), LastModified DATE)
INSERT #Tab
VALUES (1,'testemail#none.com','2019-12-01'),
(2,'testemail#none.com','2019-11-19'),
(3,'otheremail#none.com','2019-12-15')
SELECT *
FROM(
SELECT ROW_NUMBER() OVER(PARTITION BY t.Email ORDER BY t.LastModified DESC) rn, t.*
FROM #Tab t
) t2
WHERE t2.rn = 1
If by latest you mean the latest id number (the maximum number) then this should help you
With cte AS
(
SELECT email,
COUNT(id) OVER (PARTITION BY email) AS CountOfIDs,
ROW_NUMBER() OVER (PARITION BY email ORDER BY ID DESC) AS IdIndex
FROM table1
)
SELECT *
FROM cte
WHERE CountOfIDs > 1 AND IdIndex = 1

My SQL loop takes to long to complete. Is there a better way to do what I'm trying to achieve?

I am trying to de-duplicate a set of data based on certain columns. That is it isn't as easy as just SELECT DISTINCT.
I want to select from my set all rows where a column is unique. I have sorted my set in a way that I just want the loop to grab the first occurrence of the "proxy" key column. I'm saying proxy as it isn't the actual primary key of the table.
I'm using a while loop and using a counter variable based on the count of rows in a temp table. I delete each row from my temp table after processing so this should reduce the base table by the one record which was processed and any duplicate rows.
Although my code works it is seems 'cowboyish' and would like your opinion on how to do it 'cleaner' thanks
Here is my code:
declare #cnt int
set #cnt = (select COUNT(*) from #temp)
while #cnt > 0
begin
select top 1 * into #temp2 from #temp
insert into #temp3 (Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
select #temp2.*
from #temp2
left outer join #temp3 on #temp2.Member_ID = #temp3.Member_ID
where #temp3.Member_ID is null
delete #temp
from #temp
inner join #temp2 on #temp.Member_ID = #temp2.Member_ID
drop table #temp2
set #cnt = (select COUNT(*) from #temp)
end
OPTION 1:
Use below code:
WITH uniqueRecords AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY T.Member_ID ORDER BY (SELECT 1)) AS RowNum
FROM #Temp AS T
)
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT U.Member_ID, U.email, U.meeting_status,U.member_type,U.firstname,U.lastname,U.address1, U.Match_Method, U.Match_Score
FROM uniqueRecords AS U
LEFT OUTER JOIN #temp3 T3 on U.Member_ID = T3.Member_ID
WHERE U.RowNum=1
AND T3.Member_ID is null;
OPTION 2:
i) create UNIQUE INDEX on #temp3 ON Member_ID column WITH IGNORE_DUP_KEY=ON
CREATE UNIQUE INDEX UX_temp3 ON #temp3 (Member_ID) WITH (IGNORE_DUP_KEY=ON);
ii) insert result from left join of #temp and #temp3. duplicates will be ignored by IGNORE_DUP_KEY option
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT T.Member_ID, T.email, T.meeting_status,T.member_type,T.firstname,T.lastname,T.address1, T.Match_Method, T.Match_Score
FROM #temp AS T
LEFT OUTER JOIN #temp3 T3 on T.Member_ID = T3.Member_ID
WHERE T3.Member_ID is null;
If I understand your requirement correctly, you want to insert rows from #temp into #temp3, but you want to make sure that only one row from the same Member_ID gets inserted. In that case, you can use ROW_NUMBER and filter for ROW_NUMBER = 1 to make sure that only one row from duplicate Member_IDs will be inserted. Then add a NOT EXISTS filter to avoid inserting already existing rows:
INSERT INTO #temp3 (Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
SELECT
Member_ID,
email,
meeting_status,
member_type,
firstname,
lastname,
address1,
Match_Method,
Match_Score
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER (PARTITION BY Member_ID ORDER BY (SELECT NULL))
FROM #temp
) t
WHERE
t.Rn = 1
AND NOT EXISTS (
SELECT 1
FROM #temp3 t3
WHERE t3.Member_ID = t.MEMBER_ID
)
You do not have to re-count your table every time in a loop. You can simply decrement #cnt.
You should not re-create #temp2 every time in the loop. You can re-use it
You do not have to use #temp2 at all. You can just use select top 1 * from #temp instead
You do not have to use loop at all, just use following script instead:
insert into #temp3(Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
select *
from #temp
where Member_ID not in (select Member_ID from #temp3)

Get related rows from SQL Server

I have just one SQL query that I want help for.
As you can see below, there are 4 emails. 3 of the 4 messages are related (15482, 15483 and 15484). I would like to have these rows out.
You can relate them to each other through column messageid = ReplyTo and ReplyTo = MessageID. It ends up being recrusiv.
The picture below shows what I have right now, but as I said I only want the ID 15482, 15483 and 15484 shown and not 15485. Because as you can see, the first 3 rows is an email thread that hangs together while the last is a new mail
How can I do that, when I only know ID 15482
This is my SQL statement
select
t1.id, t1.From_, t1.MessageId, t2.ReplyTo
from
HelpDesk_Z01_Emails as t1
left join
HelpDesk_Z01_EmailsReplyTo as t2 on t1.MessageId = t2.MessageId
This is my output:
You correctly said that it is a recursion.
Usually it is done using recursive common table expression
I'm not sure if everything in the query below is correct. If you had provided a simplified example with sample data it would be possible to try the suggested solution. Without it, the query is written, but not tested. Give it a try.
WITH
CTE
AS
(
SELECT
t1.id, t1.From_, t1.MessageId, t2.ReplyTo
FROM
HelpDesk_Z01_Emails as t1
left join HelpDesk_Z01_EmailsReplyTo as t2 on t1.MessageId = t2.MessageId
WHERE t1.id = 15482
UNION ALL
SELECT
t1.id, t1.From_, t1.MessageId, t2.ReplyTo
FROM
HelpDesk_Z01_Emails as t1
left join HelpDesk_Z01_EmailsReplyTo as t2 on t1.MessageId = t2.MessageId
INNER JOIN CTE ON CTE.MessageId = t2.ReplyTo
)
SELECT *
FROM CTE
;
This is the script to make a simplified table with sample data that you should have included in your question:
DECLARE #T TABLE(id int, From_ varchar(255), MessageId varchar(255), ReplyTo varchar(255));
INSERT INTO #T (id, From_, MessageId, ReplyTo) VALUES (15482, 'test#com', 'CAF', NULL);
INSERT INTO #T (id, From_, MessageId, ReplyTo) VALUES (15483, 'test#com', '54c', 'CAF');
INSERT INTO #T (id, From_, MessageId, ReplyTo) VALUES (15484, 'test#com', 'Fk', '54c');
INSERT INTO #T (id, From_, MessageId, ReplyTo) VALUES (15485, 'test#com', 'FkMh', NULL);
Having such starting point it is easy to write and verify the following query:
WITH
CTE
AS
(
SELECT
TT.id, TT.From_, TT.MessageId, TT.ReplyTo
FROM
#T AS TT
WHERE TT.id = 15482
UNION ALL
SELECT
TT.id, TT.From_, TT.MessageId, TT.ReplyTo
FROM
#T AS TT
INNER JOIN CTE ON CTE.MessageId = TT.ReplyTo
)
SELECT *
FROM CTE
;
The result set:
id From_ MessageId ReplyTo
15482 test#com CAF NULL
15483 test#com 54c CAF
15484 test#com Fk 54c

How to retrieve multiple values from temp tables and insert them into another table?

I have a temp table with the following values
#TempTable
ID
1
2
for each ID in the temp table I want to execute the following:
insert into ItemOrganisationSources
select ByLineID, <TempTable.ID>, SourceTypeID
from ItemOrganisationSources
where ItemOrganisationID in (
select ID from #TempTable)
It's not clear from your code whether you have a temp table (which is prefixed by '#') or a table variable (which is prefixed by '#', like your example). Either way, though, you can reference a temp table/variable just like any other table.
Table variable:
insert into ItemOrganisationSources
select i.ByLineID, t.ID, i.SourceTypeID
from ItemOrganisationSources AS i
inner join #TempTable AS t
on i.ID = t.ID --Plug in the appropriate field to join on here
where i.ItemOrganisationID in (
select ID from #itemOrganisationIDsToBeDuplicated)
Temp table:
insert into ItemOrganisationSources
select i.ByLineID, t.ID, i.SourceTypeID
from ItemOrganisationSources AS i
inner join #TempTable AS t
on i.ID = t.ID --Plug in the appropriate field to join on here
where i.ItemOrganisationID in (
select ID from #itemOrganisationIDsToBeDuplicated)
After reading your question again, I'm not totally sure if you're trying to join your temp table to the other data, or just do the insert once for each ID in the temp table. If it's the latter, this could be a rare use for CROSS JOIN:
insert into ItemOrganisationSources
select i.ByLineID, t.ID, i.SourceTypeID
from ItemOrganisationSources AS i
cross join #TempTable AS t --cross join instead of inner join
where i.ItemOrganisationID in (
select ID from #itemOrganisationIDsToBeDuplicated)
insert into ItemOrganisationSources
select ByLineID, TT.ID, SourceTypeID
from ItemOrganisationSources IO JOIN
#TempTable TT ON TT.ID = IO.ItemOrganisationID