SQL unpivot of multiple columns - sql-server

I would like the following wide table to be unpivotted but only where a user has a true value against the field, along with the appropriate date.
Current State:
CUSTOMER_ID
First_Party_Email
Third_Party_Email
First_Party_Email_Date
Third_Party_Email_Date
40011111
1
1
2021-01-22 04:38:00.000
2021-01-17 06:38:00.000
50022222
NULL
1
NULL
2021-01-18 04:38:00.000
80066666
1
NULL
2021-01-24 05:38:00.000
NULL
_______________
_______________________
_______________________
_______________________________
_______________________________
Required State:
Customer_ID
Type
Value
Date
40011111
First_Party_Email
1
22/01/2021 04:38
40011111
Third_Party_Email
1
17/01/2021 06:38
50022222
Third_Party_Email
1
18/01/2021 04:38
80066666
First_Party_Email
1
24/01/2021 05:38
_______________________________________________________________________
Associated query to create table and my attempt that doesn't work:
create table Permissions_Obtained
(Customer_ID bigint
,First_Party_Email bit
,Third_Party_Email bit
,First_Party_Email_Date datetime
,Third_Party_Email_Date datetime
)
insert into Permissions_Obtained
(Customer_ID
,First_Party_Email
,Third_Party_Email
,First_Party_Email_Date
,Third_Party_Email_Date
)
VALUES
(40011111, 1, 1, '2021-01-22 04:38', '2021-01-17 06:38'),
(50022222, NULL, 1, NULL, '2021-01-18 04:38'),
(80066666, 1, NULL, '2021-01-24 05:38', null)
select *
from Permissions_Obtained
select
customer_id, Permission
from Permissions_Obtained
unpivot
(
GivenPermission
for Permission in (
First_Party_Email, Third_Party_Email
)
) unpiv1,
unpivot
(
GivenPermissionDate
for PermissionDate in (
First_Party_Email_Date, Third_Party_Email_Date
)
) unpiv2
where GivenPermission = 1
--drop table Permissions_Obtained
Any help would be massively appreciated. TIA

You cannot have multiple unpivots at the same time. Instead you can use Cross Apply or Inner join or union, union all or kind of joins depending on your requirement. I have added a sample answer for this using join and unpivot.
SELECT
unpvt.Customer_ID
, [Type]
, ISNULL(po.First_Party_Email ,po.Third_Party_Email) AS [Value]
,CASE WHEN unpvt.Type = 'First_Party_Email' THEN po.First_Party_Email_Date
ELSE po.Third_Party_Email_Date
END AS [Date]
FROM
(
SELECT
Customer_ID, First_Party_Email , Third_Party_Email
FROM Permissions_Obtained
) p
UNPIVOT
( [Value] FOR [Type] IN
(First_Party_Email , Third_Party_Email )
)AS unpvt
INNER JOIN Permissions_Obtained [po]
on [po].Customer_ID = unpvt.Customer_ID

When un-pivoting multiple columns, CROSS APPLY (VALUES is often the easiest and most effective solution.
It creates a virtual table per-row of the previous table, and therefore un-pivots it into separate rows.
SELECT
p.Customer_Id,
v.[Type],
v.Value,
v.Date
FROM Permissions_Obtained p
CROSS APPLY (VALUES
('First_Party_Email', p.First_Party_Email, p.First_Party_Email_Date),
('Third_Party_Email', p.Third_Party_Email, p.Third_Party_Email_Date)
) v([Type], Value, Date)
where v.Value IS NOT NULL;

Related

How can I refer to a LAG() function column in SQL Server?

I have a query in which I use LAG function :
WITH Tr AS
(
SELECT
DocDtls.Warehouse, Transactions.Code, DocDtls.zDate,
Transactions.ID, Transactions.QtyIn, Transactions.QtyOut,
Transactions.BalanceAfter
FROM
DocDtls
INNER JOIN
Transactions ON DocDtls.[PrimDocNum] = Transactions.[DocNum]
)
SELECT
ID, Code, QtyIn, QtyOut, BalanceAfter,
LAG(BalanceAfter, 1, 0) OVER (PARTITION BY Warehouse, Code
ORDER BY Code, ID) Prev_BlncAfter
FROM
Tr;
It's working fine but when I try to add this column before FROM:
SUM(Prev_BlncAfter + QtyIn) - QtyOut AS NewBlncAfter
I get this error :
Msg 207, Level 16, State 1, Line 3
Invalid column name 'Prev_BlncAfter'
How can I fix this ? Thanks
You can create the LAG column inside the CTE instead of in the outer query. E.g.
declare #DocDtls table (Warehouse int, zDate date, [PrimDocNum] int);
declare #Transactions table (code int, id int, QtyIn int, QtyOut int, balanceafter int, [DocNum] int)
;with Tr As
(
SELECT
d.Warehouse
, t.Code
, d.zDate
, t.ID
, t.QtyIn
, t.QtyOut
, t.BalanceAfter
,LAG(BalanceAfter,1,0) Over (partition by Warehouse,Code order by Code,ID) Prev_BlncAfter
FROM #DocDtls d
INNER JOIN #Transactions t ON d.[PrimDocNum] = t.[DocNum]
)
select ID,Code,QtyIn,QtyOut,BalanceAfter
,SUM(Prev_BlncAfter + QtyIn)-QtyOut As NewBlncAfter
from Tr
group by ID,Code,QtyIn,QtyOut,BalanceAfter;
You can nest this query to refer the newly added column from the outer scope, or create another with like you've done before for referencing it afterwards:
with Tr As (
SELECT
DocDtls.Warehouse,
Transactions.Code,
DocDtls.zDate,
Transactions.ID,
Transactions.QtyIn,
Transactions.QtyOut,
Transactions.BalanceAfter
FROM
DocDtls
INNER JOIN Transactions ON DocDtls.[PrimDocNum] = Transactions.[DocNum]
),
formatted_tr as (
select
ID,
Code,
QtyIn,
QtyOut,
BalanceAfter,
LAG(BalanceAfter, 1, 0) Over (
partition by Warehouse,
Code
order by
Code,
ID
) Prev_BlncAfter
from
Tr
)
select
SUM(Prev_BlncAfter + QtyIn) - QtyOut As NewBlncAfter
from
formatted_tr
group by
ID, QtyOut
;
Based on comments , I combined the two answers to get what I need :
with Tr As (
SELECT
DocDtls.Warehouse,
Transactions.Code,
DocDtls.zDate,
Transactions.ID,
Transactions.QtyIn,
Transactions.QtyOut,
Transactions.BalanceAfter
FROM
DocDtls
INNER JOIN Transactions ON DocDtls.[PrimDocNum] = Transactions.[DocNum]
),
formatted_tr as (
select
ID,
Code,
QtyIn,
QtyOut,
BalanceAfter,
LAG(BalanceAfter, 1, 0) Over (
partition by Warehouse,
Code
order by
Code,zDate,ID
) Prev_BlncAfter
from
Tr
)
select ID,Code,QtyIn,QtyOut,BalanceAfter
,SUM(Prev_BlncAfter + QtyIn)-QtyOut As NewBlncAfter
from formatted_tr
group by ID,Code,QtyIn,QtyOut,BalanceAfter;
;

Using recursion with a CTE in SQL Server

I have following table Structure: (this is just a sample set with exact same columns in my final output query)
Actual data has a much higher number of rows in index and I have to remove few symbols before arriving to the index value. This is a custom index to be built for internal use.
https://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=b1d5ed7db79c665d8cc179ae4cc7d4f1
This is link to the fiddle for SQL data
below is the image of the same:
I want to calculate point contribution to the index value and finally the index value.
To calculate pts contribution by each symbol the formula is :
ptsC = yesterday_index * wt * px_change / yest_close
I do not have beginning value of yesterday Index .i.e for 17 Nov 2021 and should be considered as 1000
The Index Value of 18 Nov will then be 1000 + sum(ptsC)
This value should now be used to calculate ptsC for each symbol for 22-Nov and so on...
I am trying to write a recursive CTE but am not sure where I am going wrong.
Yesterday Index value should be recursively determined and thus the ptsC should be calculated.
The final output should be:
where total Point Contribution is sum of all the ptsC for the day and New index Value is yesterday Index Value + Total Point Contribution.
Below is the code I have which generates the first table:
declare #beginval as float=17671.65
set #beginval=1000
declare #indexname varchar(20)='NIFTY ENERGY'
declare #mindt as datetime
select #mindt=min(datetime) from indices_json where indexname=#indexname
;
with tbl as (
SELECT IndexName, datetime, sum(Indexmcap_today) totalMcap_today,sum(Indexmcap_yst) totalmcap_yst
FROM indices_json
WHERE IndexName = #indexname
group by indexname,datetime
)
,tbl2 as
(
select j.indexname,j.datetime,symbol,Indexmcap_today/d.totalMcap_today*100 calc_wt_today,Indexmcap_yst/d.totalmcap_yst*100 calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
from indices_json j inner join tbl d on d.datetime=j.datetime and d.IndexName=j.IndexName
)
,tbl3 as
(
select indexname,datetime,symbol,calc_wt_today,calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
,case when datetime=#mindt then #beginval*calc_wt_yest*iislPtsChange/adjustedClosePrice/100 else null end ptsC
from tbl2
)
,tbl4 as
(
select indexname,datetime,sum(ptsC) + #beginval NewIndexVal,sum(pointchange) PTSCC
from tbl3
group by indexname,datetime
)
,tbl5 as
(
select *,lag(datetime,1,null) over(order by datetime asc) yest_dt
from tbl4
)
,
tbl6 as
(
select d.*,s.yest_dt
from tbl2 d inner join tbl5 s on d.datetime=s.datetime
)
,tbl7 as
(
select d.IndexName,d.datetime,d.symbol,d.calc_wt_today,d.calc_wt_yest,d.iislPtsChange,d.adjustedClosePrice,d.pointchange,case when i.datetime is null then #beginval else i.NewIndexVal end yest_index
from tbl6 d left join tbl4 i on d.yest_dt=i.datetime
)
select IndexName,convert(varchar(12),datetime,106)date,symbol,round(calc_wt_yest,4) wt,iislPtsChange px_change,adjustedClosePrice yest_close--,pointchange,yest_index
from tbl7 d where datetime <='2021-11-24'
order by datetime
Thanks in advance.
I found a solution for this:
I calculated the returns for each constituent for each date
then summed up these returns for a date
then multiplied all the sum of the returns of all dates to arrive at the final value - this works
below is the query for the same. I did not require recursion here
declare #beginval as float=17671.65
declare #indexname varchar(20)='NIFTY 50'
declare #mindt as datetime
select #mindt=min(datetime) from indices_json where indexname=#indexname
declare #startdt as datetime = '2021-11-01'
;
with tbl as (
SELECT IndexName, datetime, sum(Indexmcap_today) totalMcap_today,sum(Indexmcap_yst) totalmcap_yst
FROM indices_json
WHERE IndexName = #indexname-- and symbol!='AXISBANK'
group by indexname,datetime
)
,tbl2 as
(
select j.indexname,j.datetime,symbol,Indexmcap_today/d.totalMcap_today*100 calc_wt_today,Indexmcap_yst/d.totalmcap_yst*100 calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
from indices_json j inner join tbl d on d.datetime=j.datetime and d.IndexName=j.IndexName
)
,tbl7 as
(
select d.IndexName,d.datetime,d.symbol,d.calc_wt_today,d.calc_wt_yest,d.iislPtsChange,d.adjustedClosePrice,d.pointchange, d.calc_wt_yest*d.iislPtsChange/d.adjustedClosePrice/100 ret
from tbl2 d
)
,tbl8 as
(
select indexname,datetime,1+sum(ret) tot_ret from tbl7 group by indexname,datetime
)
select indexname,datetime date
,round(exp(sum(log(sum(tot_ret))) over (partition by IndexName order by datetime)),6)*#beginval final_Ret
from tbl8 where datetime>=#startdt
group by indexname,datetime order by date

MSSQL: Select max date when a specific column was updated

I need to return the last records which had a certain column updated.
The data is stored in 2 tables: ClientInfo and ClientInfoHistory both of them with a large amount of data, especially the history one (which keeps track on any changes on the main table ClientInfo). Even if only one column was updated in ClientInfo, a row with the version before that update will be inserted into ClientInfoHistory with audit info (the user and the date when that row was updated).
So I am interested in returning the max date when the Flag3 was changed for each ClientID + the user who changed that and the value of Flag3
The entire script should be in a stored proc avoiding perf issues.
My idea:
I create a temp table with the entire customer's history + actual data, then I compare the Flag3 to see when that flag was changed for each customer and throw it into another temp table along with the modifiedbyuserid and modifieddate. Then I select max(modifiedDate) for each customer.
The tables look like this:
create table dbo.ClientInfo(
ClientID int,
Flag1 bit,
Flag2 bit,
Flag3 bit,
CreatedByUserID int not null,
CreatedDate datetime not null default getdate(),
ModifiedByUserID int not null,
ModifiedDate datetime not null default getdate(),
constraint PK_UserInfo primary key (ClientID)
)
create table dbo.ClientInfoHistory(
ClientInfoHistoryID bigint identity not null,
ClientID int,
Flag1 bit,
Flag2 bit,
Flag3 bit,
CreatedByUserID int not null,
CreatedDate datetime not null,
HistoryStartModifiedByUserID int not null,
HistoryStartDate datetime not null,
HistoryEndModifiedByUserID int not null,
HistoryEndDate datetime not null,
constraint PK_ClientInfoHistory primary key (ClientInfoHistoryID)
)
CREATE NONCLUSTERED INDEX ix_ClientInfoHistory_ClientID_HistoryDates
on dbo.ClientInfoHistory (ClientID, HistoryStartDate, HistoryEndDate)
The temp table with the entire customer's history + actual data contains this:
SELECT c.ClientID
,c.Flag3
,c.ModifiedDate as HistoryStartDate
,'9999-12-31' as HistoryEndDate
,c.ModifiedByUserId as HistoryStartModifiedByUserID
FROM dbo.ClientInfo c with (nolock)
UNION
SELECT
ch.ClientID
,ch.Flag3
,ch.HistoryStartDate
,ch.HistoryEndDate
,ch.HistoryStartModifiedByUserID
FROM dbo.ClientInfoHistory ch with (nolock)
insert into dbo.ClientInfo (ClientID, Flag1, Flag2, Flag3, CreatedByUserID, CreatedDate, ModifiedByUserID, ModifiedDate)
values
(1,0,0,1,1234,'2019-05-29 04:57:13.360', 1111,'2019-07-01 08:35:13.360'),
(2,0,1,0,1233,'2019-03-12 04:57:13.360', 1233, '2019-03-12 04:57:13.360')
insert into dbo.ClientInfoHistory (ClientID, Flag1, Flag2, Flag3, CreatedByUserID, CreatedDate, HistoryStartModifiedByUserID,HistoryStartDate, HistoryEndModifiedByUserID, HistoryEndDate )
values
(1,1,1,1,1234,'2019-05-29 04:57:13.360', 1234, '2019-05-29 04:57:13.360', 4321,'2019-05-31 04:57:13.360'),
(1,0,1,1,1234,'2019-05-29 04:57:13.360', 4321,'2019-05-31 04:57:13.360', 9871,'2019-06-02 06:27:13.360'),
(1,0,1,0,1234,'2019-05-29 04:57:13.360',9871,'2019-06-02 06:27:13.360', 8765,'2019-06-21 11:06:13.360'),
(1,0,0,0,1234,'2019-05-29 04:57:13.360',8765,'2019-06-21 11:06:13.360', 9871,'2019-06-22 06:27:13.360')
(1,0,0,1,1234,'2019-05-29 04:57:13.360',9871,'2019-06-22 06:27:13.360', 4321,'2019-06-25 08:35:13.360'),
(1,0,1,1,1234,'2019-05-29 04:57:13.360',4321,'2019-06-25 08:35:13.360', 1111,'2019-07-01 08:35:13.360')
So for example above...The changes of that flag are:
ClientID,Flag3,ModifiedByUserID,ModifiedDate
1, 1, 1234, 29/05/2019
1, 0, 9871, 02/06/2019
1, 1, 9871, 22/06/2019***
2, 0, 1233, 12/03/2019***
and the final set of results should return only those rows marked with *** (the last version of Flag3 for each ClienID)
I am not so happy with the enitre process I chose and I am looking for another solution with a better performance. I would be really happy to hear some ideas from you guys
Following query must give you expected result
SELECT *
FROM (
SELECT *, ROW_NUMBER () OVER (PARTITION BY ch.ClientID ORDER BY ch.HistoryStartDate DESC) as Rn
FROM
(
SELECT c.ClientID
,c.Flag3
,c.ModifiedDate as HistoryStartDate
,'9999-12-31' as HistoryEndDate
,c.ModifiedByUserId as HistoryStartModifiedByUserID
-- ,ROW_NUMBER () OVER (PARTITION BY c.ClientID ORDER BY c.ModifiedDate DESC) as Rn
FROM dbo.ClientInfo c with (nolock)
UNION
SELECT
ch.ClientID
,ch.Flag3
,ch.HistoryStartDate
,ch.HistoryEndDate
,ch.HistoryStartModifiedByUserID
--,ROW_NUMBER () OVER (PARTITION BY ch.ClientID ORDER BY ch.HistoryStartDate DESC) as Rn
FROM dbo.ClientInfoHistory ch with (nolock)
) as CH
) AS T
WHERE T.Rn = 1
Your question was not exactly clear, but I believe this is what you are looking for.
You will probably want to change your indexing around a little to include Flag3, and depending on the size of your data you might consider indexing the temp table. But this is a quick and dirty query to get you started
;WITH CTE AS
(select t2.ClientID, MAX(HistoryStartDate) NotMatchDate
from #ClientInfo t1
INNER JOIN #ClientInfoHistory t2 on t1.ClientID = t2.ClientID and t1.Flag3 <> t2.Flag3
GROUP BY t2.ClientID
)
select t2.ClientID, MIN(HistoryStartDate) ModifiedDate
INTO #tmpClient
from #ClientInfo t1
INNER JOIN #ClientInfoHistory t2 on t1.ClientID = t2.ClientID and t1.Flag3 = t2.Flag3
INNER JOIN CTE t3 on t3.ClientID = t1.ClientID
WHERE t2.HistoryStartDate > t3.NotMatchDate
GROUP BY t2.ClientID
SELECT t1.ClientID, t1.Flag3,t1.HistoryStartModifiedByUserID ModifiedByUserID, t1.HistoryStartDate ModifiedDate
FROM #ClientInfoHistory t1
INNER JOIN #tmpClient t2 on t1.ClientID = t2.ClientID and t1.HistoryStartDate = t2.ModifiedDate
UNION ALL
SELECT t1.ClientID, Flag3,CreatedByUserID ModifiedByUserID,CreatedDate ModifiedDate
FROM #ClientInfo t1
LEFT JOIN #tmpClient t2 on t1.ClientID = t2.ClientID
WHERE t2.ClientID IS NULL
EDIT #2: Fixed for new rows

Update latest record with data from an older record

I have a table with newspaper subscribers:
Subscribers:
==============
ID INT,
Status,
Address,
IndexAddress,
StartDate,
EndDate,
SubscriberID,
PaperID
IndexAddress is a reference to my internal Address table where I keep "correct" addresses (you woulnd't believe how many people don't know where they live). Address is the address supplied by the customer.
Each time a subscriber ends his subscription I save the data and when he renews his subscription I want to re-fetch the old IndexAddress from the old subscrption line in my table.
The data in the database can look like this:
1 1 MyLocalAddress 13455 20160101 20160501 100 5
8 1 MyLocalAddress 13455 20160820 20161201 100 5
14 1 MyLocalAddress 13455 20161228 20170107 100 5
18 0 MyLocalAddress NULL 20170109 NULL 100 5
So ID 1, has status 1, a local address, pointing to address 13455 in my internal system, started 160101 and ended 160501 with customer number 100 and paper number 5.
The last row, ID 18 has just arrived in the database, I want to make sure I automatically find the IndexAddress number so I don't have to match it by hand, but I also want to make absolutlely sure that I fetch the information from the row with ID 14 since the older information in the database MIGHT be wrong (in this case it isn't but it might).
Here is my SQL to fix this:
UPDATE s SET
Status = s2.Status,
IndexAddress = s2.IndexAddress
FROM dbo.Subscribers s
JOIN dbo.Subscribers s2 ON s2.SubscriberID = s.SubscriberID
WHERE 1 = 1
AND s.Status <> s2.Status
AND s2.Status = 1
AND s2.ID IN
(
SELECT
MAX(s3.ID)
FROM dbo.Subscribers s3
WHERE 1 = 1
AND s3.SubscriberID = s.SubscriberID
AND s3.PaperID = s.PaperID
AND s3.Status = 1
AND s3.ID <> s.ID
)
-- Make sure it's the same customer. Customer number is checked in
-- join above.
AND s.PaperID = s2.PaperID
AND s.Address = s2.Address
This works, but I wanted to know if the subquery approach was the best solution or is there a better approach?
I would like to deepen my understand of MS SQL and thus my questions.
I think your query is way over complicated:
with toupdate as (
select s.*,
lag(address) over (partition by subscriberid, paperid order by id) as prev_address,
lag(status) over (partition by subscriberid, paperid order by id) as prev_status
from dbo.Subscribers s
)
update toupdate
set address = prev_address,
status = prev_status
where address is null;
This is not the answer you're looking for but it's not really suitable for a comment. I don't really agree with the design of the tables as you have redundant data. You shouldn't have to repeat data for address and indexaddress in Subscribers or do updates like you are doing.
I would suggest a design something like the below that would avoid you having to do updates like the one you are doing. The below code is re-runnable, so you can run and modify if required to test it.
-- user level information with 1 row per user - address should be linked here
CREATE TABLE #user
(
id INT ,
name NVARCHAR(20) ,
indexAddress INT
)
-- all subscriptions - with calculated status compared to current date
CREATE TABLE #subscription
(
id INT ,
startDate DATETIME ,
endDate DATETIME ,
staus AS CASE WHEN endDate < GETDATE() THEN 1
ELSE 0
END
)
-- table to link users with their subscriptions
CREATE TABLE #userSubscription
(
userId INT ,
subscriptionId INT
)
INSERT INTO #user
( id, name, indexAddress )
VALUES ( 1, N'bob', 13455 ),
( 2, 'dave', 55332 )
INSERT INTO #subscription
( id, startDate, endDate )
VALUES ( 1, '20160101', '20160201' ),
( 8, '20160820', '20161201' ),
( 14, '20161228', '20170107' ),
( 18, '20170109', NULL ),
( 55, '20170101', NULL );
INSERT INTO #userSubscription
( userId, subscriptionId )
VALUES ( 1, 1 ) ,
( 1, 8 ) ,
( 1, 14 ) ,
( 1, 18 ) ,
( 2, 55 );
-- show active users
SELECT u.name ,
u.indexAddress ,
us.userId ,
us.subscriptionId ,
s.startDate ,
s.endDate ,
s.staus
FROM #user u
INNER JOIN #userSubscription us ON u.id = us.userId
INNER JOIN #subscription s ON s.id = us.subscriptionId
WHERE s.staus = 0 -- active
-- show inactive users
SELECT u.name ,
u.indexAddress ,
us.userId ,
us.subscriptionId ,
s.startDate ,
s.endDate ,
s.staus
FROM #user u
INNER JOIN #userSubscription us ON u.id = us.userId
INNER JOIN #subscription s ON s.id = us.subscriptionId
WHERE s.staus = 1 -- inactive
-- tidy up
DROP TABLE #subscription
DROP TABLE #user
DROP TABLE #userSubscription

SQL Joins Please help me the below

I have data In two tables like below:
I need the third table output. I have used joins but it is not working. I have used rank also.
SELECT
a.requestinstancelogid AS requestinstancelogidIn,
a.requestinstanceid AS InRequestInstance,
a.requeststatuscdid AS Inrequeststatuscdid,
a.Addnldocsin,
b.requestinstancelogid AS requestinstancelogidOut,
b.requestinstanceid AS OutRequestInstance,
b.requeststatuscdid AS Outrequeststatuscdid,
b.AddnldocsOut,
RANK() OVER (PARTITION BY a.requestinstanceid ORDER BY a.requestinstancelogid) AS one,
RANK() OVER (PARTITION BY b.requestinstanceid ORDER BY b.requestinstancelogid) AS two
INTO
#tmp_MultipleAddnlDocsLender
FROM
#tmp_addnldocsin a
LEFT JOIN
#tmp_addnldocsout b ON a.requestinstanceid = b.requestinstanceid
WHERE
a.requestinstanceid = 164944
This query returns 6 records.
The only way i can see that you could produce these results is the following:
;WITH Table1CTE AS
(
SELECT *,
ROW_NUMBER()OVER(PARTITION BY requestinstanceidin ORDER BY requestinstancelogid) AS rn
FROM Table1
), Table2CTE AS
(
SELECT *,
ROW_NUMBER()OVER(PARTITION BY requestinstanceidout ORDER BY requestinstancelogid) AS rn
FROM Table2
)
SELECT *
FROM Table1CTE T1
LEFT JOIN Table2CTE T2
ON T1.requestinstanceidin = T2.requestinstanceidout
AND T1.rn= T2.rn
As far as I can tell, the same column in both is the requestinstanceidout (could hardly read it, please post text or code next time)
Based on the idea of the above is correct, you could have something like this:
SELECT
*
FROM
table1 a
LEFT JOIN table 2 b
ON a.requestinstanceidin = b.requestinstanceidout
Hope this will help you!
I believe this is what you're looking for:
declare #request_instance_log_id_in table (
[log] [int]
, [in] [int]
, [status] [int]
, [created] [datetime] default current_timestamp);
insert into #request_instance_log_id_in
([log],[in],[status])
values (424593,164944,110),
(424594,164944,110),
(424595,164944,110);
declare #request_instance_log_id_out table (
[log] [int]
, [out] [int]
, [status] [int]
, [created] [datetime] default current_timestamp);
insert into #request_instance_log_id_out
([log],[out],[status])
values (424593,164944,112),
(424594,164944,112);
select [request_instance_log_id_in].[log] as [request_instance_log_id_in_log]
, [request_instance_log_id_in].[in] as [request_instance_log_id_in_in]
, [request_instance_log_id_in].[status] as [request_instance_log_id_in_status]
, [request_instance_log_id_in].[created] as [request_instance_log_id_in_created]
, [request_instance_log_id_out].[log] as [request_instance_log_id_out_log]
, [request_instance_log_id_out].[out] as [request_instance_log_id_out_out]
, [request_instance_log_id_out].[status] as [request_instance_log_id_out_status]
, [request_instance_log_id_out].[created] as [request_instance_log_id_out_created]
from #request_instance_log_id_in as [request_instance_log_id_in]
left join #request_instance_log_id_out as [request_instance_log_id_out]
on [request_instance_log_id_out].[log] = [request_instance_log_id_in].[log];
request_instance_log_id_in_log request_instance_log_id_in_in request_instance_log_id_in_status request_instance_log_id_in_created request_instance_log_id_out_log request_instance_log_id_out_out request_instance_log_id_out_status request_instance_log_id_out_created
424593 164944 110 2014-09-02 08:55:01.107 424593 164944 112 2014-09-02 08:55:01.107
424594 164944 110 2014-09-02 08:55:01.107 424594 164944 112 2014-09-02 08:55:01.107
424595 164944 110 2014-09-02 08:55:01.107 NULL NULL NULL NULL
I think you need a cross/outer apply
like this
SELECT
a.requestinstancelogid AS requestinstancelogidIn,
a.requestinstanceid AS InRequestInstance,
a.requeststatuscdid AS Inrequeststatuscdid,
a.Addnldocsin,
q.requestinstancelogid AS requestinstancelogidOut,
q.requestinstanceid AS OutRequestInstance,
q.requeststatuscdid AS Outrequeststatuscdid,
q.AddnldocsOut
FROM #tmp_addnldocsin a
OUTER APPLY (SELECT TOP 1
b.requestinstancelogid AS requestinstancelogidOut,
b.requestinstanceid AS OutRequestInstance,
b.requeststatuscdid AS Outrequeststatuscdid,
b.AddnldocsOut
FROM #tmp_addnldocsout b
WHERE a.requestinstanceidin = b.requestinstanceidout
ORDER BY AddnIdocsOut DESC) q
WHERE
a.requestinstanceid = 164944

Resources