SQL Joins Please help me the below - sql-server

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

Related

SQL unpivot of multiple columns

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;

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

What is the most efficient way to compare a table against itself in SQL server?

I have recently developed some coding that will identify first call resolution for an insurance company that I currently work for. The code basically creates two identical SELECT statements from a call data table, sorts and ranks the data by a member_id, call_date and call_time and then compares each query against one another where the member_id and call_type are equal, but the "rank" or RowId is not (so the comparison happens for each Rowid from one side of the inner join to the other but not for the same Rowid). This acts as a quasi "loop" to compare all the records to see where the call_dates are > 14 days OR where the call_dates are equal AND the call_times are > 24 hours....for the same call_type and same member_id.
Here is a sample of the code:
DECLARE #Temp TABLE (
[MEM_ID] [varchar](10) NULL,
[CALL_DATE] [datetime2](3) NULL,
[CALL_TIME] [varchar](8) NULL,
[OPER_CODE] [varchar](8) NULL,
[TEXT_DEPT] [varchar](6) NULL,
[CAT_DESC] [varchar](30) NULL
)
INSERT INTO #Temp
VALUES ('00000-1400', '2018-07-16 00:00:00.000','10:12:23','YYZ2500','SERV06','PLAN BENEFITS')
,('00000-1400', '2018-06-10 00:00:00.000','10:12:23','YYZ2500','SERV06','PLAN BENEFITS')
,('00000-1400', '2018-07-01 00:00:00.000','18:12:23','YYZ2500','SERV06','CLAIMS')
,('00000-1400', '2018-07-02 00:00:00.000','05:12:23','YYZ2500','SERV06','OTHER')
,('00000-1400', '2018-07-14 00:00:00.000','02:12:23','YYZ2500','SERV06','CLAIMS')
,('00000-1400', '2018-07-27 00:00:00.000','11:12:23','YYZ2500','SERV06','PLAN BENEFITS')
,('00000-1400', '2018-06-30 00:00:00.000','08:12:23','YYZ2500','SERV06','PLAN BENEFITS')
,('00000-1400', '2018-06-29 00:00:00.000','07:12:23','YYZ2500','SERV06','AUTHORIZATIONS')
,('00000-1400', '2018-06-29 00:00:00.000','07:26:23','YYZ2500','SERV06','AUTHORIZATIONS')
,('00000-1400', '2018-06-25 00:00:00.000','09:38:23','YYZ2500','SERV06','OTHER')
Select Calc.*, CASE WHEN Calc.Disposition = 'No subsequent within 14' THEN CONVERT(tinyint, 1) ELSE 0 END as FCR_Ind
From (Select DISTINCT Final.RowID, Final.CallCount, Final.MEM_ID, Final.CALL_DATE,
Final.CALL_TIME, Final.CAT_DESC, Final.OPER_CODE, Final.TEXT_DEPT,
CASE WHEN Final.[Had a subsequent within 14 days] IS NULL
THEN 'No subsequent within 14' ELSE Final.[Had a subsequent within 14 days]
END as Disposition
From (Select *
From (Select DISTINCT T1.RowID, T1.CallCount, T1.MEM_ID, T1.CALL_DATE,
T1.CALL_TIME, T1.CAT_DESC, T1.OPER_CODE, T1.TEXT_DEPT,
CASE WHEN T2.CALL_DATE BETWEEN T1.CALL_DATE AND DateAdd(DAY, 14, T1.CALL_DATE) AND T2.RowID <> T1.RowID AND T2.CALL_DATE <> T1.CALL_DATE OR T2.CALL_TIME BETWEEN T1.CALL_TIME AND DateAdd(HOUR, 24, T1.CALL_DATE) AND T2.RowID <> T1.RowID AND T2.CALL_DATE = T1.CALL_DATE THEN 'Had a subsequent within 14 days' END as Disposition
From (Select ROW_NUMBER() OVER (PARTITION BY MEM_ID ORDER BY MEM_ID,
[CALL_DATE], CALL_TIME) AS RowID, Count(CALL_TIME) as CallCount,
MEM_ID, [CALL_DATE], CALL_TIME, CAT_DESC, OPER_CODE, TEXT_DEPT
From #Temp
Group by MEM_ID, [CALL_DATE], CALL_TIME, CAT_DESC, OPER_CODE,
TEXT_DEPT) as T1
Inner Join (Select ROW_NUMBER() OVER (PARTITION BY MEM_ID ORDER BY MEM_ID,
[CALL_DATE], CALL_TIME) AS RowID, Count(CALL_TIME) as
CallCount, MEM_ID, [CALL_DATE], CALL_TIME, CAT_DESC,
OPER_CODE, TEXT_DEPT
From #Temp
Group by MEM_ID, [CALL_DATE], CALL_TIME, CAT_DESC, OPER_CODE,
TEXT_DEPT) as T2
ON T1.MEM_ID = T2.MEM_ID AND T1.CAT_DESC = T2.CAT_DESC ) as Sub
PIVOT( MAX(Sub.Disposition)
FOR Sub.Disposition IN ([Had a subsequent within 14 days])) AS PivotTable) as Final) as Calc
The Output yields the following:
I know this is not the most efficient way to solve this problem and was wondering if there is a way to write the INNER JOIN portion where only 1 of the sorted tables is used to iterate thru out the records of the 2nd sorted table instead of each table iterating against each other? I appreciate any insights on how to make this code use less system resources and make it more efficient from an execution plan standpoint.
Thanks!!

OPTIMIZE FOR UNKNOWN when doing a UNION

So I have a few really slow queries in SP's I need to speed up, I have been using OPTIMIZE FOR UNKNOWN and seeing some dramatic increases in performance. I still have one query that really is slow and I want to apply this but it contains a UNION of 2 SQL Queries, so my question is do I apply the OPTIMIZE FOR UNKNOWN to both?
THIS IS A GREATLY SIMPLIFIED VERSION OF MY SP FOR CLARITY:
SELECT * FROM MyTable ManufacturerID=#ManufacturerID and tStamp > #tStamp
OPTION (OPTIMIZE FOR (#ManufacturerID UNKNOWN, #tStamp UNKNOWN))
UNION
SELECT * FROM MyTable ManufacturerID=#ManufacturerID
OPTION (OPTIMIZE FOR (#ManufacturerID UNKNOWN)
Here is the actual SP as it stand right now:
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY Products.ItemID) AS RowNum, *
FROM
(
SELECT Products.ProductID, Products.ItemID, Products.ManufacturerID,
CategoryID = NULL, CategoryName = NULL,
CategoryProductID = NULL, Products.ItemName, Products.Description, Products.Notes,
Products.Dimensions, Products.BasePrice, Products.OrderMinimumQuantity,
ContainerMinimumQuantity =
CASE COALESCE(Products.ContainerMinQty, 0)
WHEN 0 THEN Products.OrderMinimumQuantity
ELSE Products.ContainerMinQty
END
, Products.OrderMultipleQuantity, Products.OnHandQuantity,
Products.Category, Products.IntroDate, Products.BackOrderDate, Products.UPC, Products.PriceLevel1, Products.PriceLevel2, Products.PriceLevel3,
Products.PriceLevel4, Products.PriceLevel5, Products.PriceLevel6, Products.PriceLevel7, Products.PriceLevel8, Products.PriceLevel9, Products.PieceBox,
Products.Cubes, Products.UnitOfMeasure, Products.UDF1, Products.UDF2, Products.UDF3, Products.UDF4, Products.UDF5, Products.AdditionalImageCount,
PhotoName= LOWER(Products.PhotoName), Products.Discontinued, Products.ModifiedOn,
Products.IsDeleted, Products.PriceLevel10, Products.PriceLevel11, Products.PriceLevel12, Products.PriceLevel13,
Products.PriceLevel14, Products.PriceLevel15, Products.PriceLevel16, Products.PriceLevel17, Products.PriceLevel18, Products.PriceLevel19, Products.PriceLevel20,
Products.Weight, Products.DimensionsMetric, Products.Source, Products.InventoryStatus, Products.CatalogCode, Products.CatalogName,
SortOrder = NULL,
Products.reportCategory,Products.additionalPhotos,Products.udf6,Products.udf7,Products.udf8,
Products.udf9,Products.udf10,Products.udf11,Products.udf12,Products.udf13,Products.udf14,Products.udf15,Products.udf16,
Products.udf17,Products.udf18,Products.udf19,Products.udf20, Products.showRelatedFor,Products.showChildFor
FROM
CategoryProducts (nolock) RIGHT OUTER JOIN
Products (nolock) ON CategoryProducts.ManufacturerID = Products.ManufacturerID AND CategoryProducts.ItemID = Products.ItemID
WHERE (Products.ManufacturerID = #ManufacturerID)
AND
(Products.ModifiedOn > #tStamp ) AND ((CategoryProducts.IsDeleted = 1) OR (CategoryProducts.IsDeleted IS NULL)
)
UNION
SELECT Products.ProductID, Products.ItemID, Products.ManufacturerID, Categories.CategoryID, Categories.CategoryName, CategoryProducts.CategoryProductID, Products.ItemName, Products.Description, Products.Notes,
Products.Dimensions, Products.BasePrice, Products.OrderMinimumQuantity,
ContainerMinimumQuantity =
CASE COALESCE(Products.ContainerMinQty, 0)
WHEN 0 THEN Products.OrderMinimumQuantity
ELSE Products.ContainerMinQty
END
, Products.OrderMultipleQuantity, Products.OnHandQuantity,
Products.Category, Products.IntroDate, Products.BackOrderDate, Products.UPC, Products.PriceLevel1, Products.PriceLevel2, Products.PriceLevel3,
Products.PriceLevel4, Products.PriceLevel5, Products.PriceLevel6, Products.PriceLevel7, Products.PriceLevel8, Products.PriceLevel9, Products.PieceBox,
Products.Cubes, Products.UnitOfMeasure, Products.UDF1, Products.UDF2, Products.UDF3, Products.UDF4, Products.UDF5, Products.AdditionalImageCount,
PhotoName= LOWER(Products.PhotoName), Products.Discontinued, Products.ModifiedOn,
CategoryProducts.IsDeleted, Products.PriceLevel10, Products.PriceLevel11, Products.PriceLevel12, Products.PriceLevel13,
Products.PriceLevel14, Products.PriceLevel15, Products.PriceLevel16, Products.PriceLevel17, Products.PriceLevel18, Products.PriceLevel19, Products.PriceLevel20,
Products.Weight, Products.DimensionsMetric, Products.Source, Products.InventoryStatus, Products.CatalogCode, Products.CatalogName,
CategoryProducts.SortOrder,
Products.reportCategory,Products.additionalPhotos,Products.udf6,Products.udf7,Products.udf8,
Products.udf9,Products.udf10,Products.udf11,Products.udf12,Products.udf13,Products.udf14,Products.udf15,Products.udf16,
Products.udf17,Products.udf18,Products.udf19,Products.udf20, Products.showRelatedFor,Products.showChildFor
FROM Categories (nolock) INNER JOIN
CategoryProducts (nolock) ON Categories.CategoryID = CategoryProducts.CategoryID INNER JOIN
Products (nolock) ON CategoryProducts.ManufacturerID = Products.ManufacturerID AND CategoryProducts.ItemID = Products.ItemID
WHERE (Products.ManufacturerID = #ManufacturerID)
AND
(Products.ModifiedOn > #tStamp OR CategoryProducts.ModifiedOn > #tStamp)
) AS Products
) AS C WHERE RowNum >= #StartRow AND RowNum <= #EndRow ORDER BY ItemID, ManufacturerID
OPTION (OPTIMIZE FOR (#ManufacturerID UNKNOWN, #StartRow UNKNOWN, #EndRow UNKNOWN, #tStamp UNKNOWN))
From Books Online (Query Hints):
Query hints specify that the indicated hints should be used throughout
the query. They affect all operators in the statement. If UNION is
involved in the main query, only the last query involving a UNION
operation can have the OPTION clause.
So that's pretty explicit that you can only use OPTION once, not twice like in your example.
That makes sense, since even though there are two SELECT statements put together, SQL Server will still treat it as one overall statement for the purposes of compilation and optimization.
This does mean that if you want to use different hints in the different statements that make up the UNION you'll have to go about it a different way, e.g. using TEMP tables to store the interim results.
So, in your specific example, even though #tStamp is only in the first SELECT statement, you can still reference it in the one OPTION clause as required.
Try this one -
SELECT
p.ProductID
, RowNum = ROW_NUMBER() OVER(ORDER BY p.ItemID)
, p.ItemID
, p.ManufacturerID
, CategoryID = NULL
, CategoryName = NULL
, CategoryProductID = NULL
, p.ItemName
, p.[Description]
, p.Notes
, p.Dimensions
, p.BasePrice
, p.OrderMinimumQuantity
, ContainerMinimumQuantity =
CASE WHEN ISNULL(p.ContainerMinQty, 0) = 0
THEN p.OrderMinimumQuantity ELSE p.ContainerMinQty
END
, p.OrderMultipleQuantity
, p.OnHandQuantity
, p.category
, p.IntroDate
, p.BackOrderDate
, p.UPC
...
, p.PieceBox
, p.Cubes
, p.UnitOfMeasure
, p.UDF1, p.UDF2, p.UDF3
, p.UDF4, p.UDF5
, p.AdditionalImageCount
, PhotoName = LOWER(p.PhotoName)
, p.Discontinued
, p.ModifiedOn
, p.IsDeleted
...
, p.[Weight]
, p.DimensionsMetric
, p.[Source]
, p.InventoryStatus
, p.CatalogCode
, p.CatalogName
, SortOrder = NULL
, p.reportCategory
, p.additionalPhotos
....
, p.showRelatedFor
, p.showChildFor
FROM dbo.Products p WITH(NOLOCK)
--LEFT JOIN (
-- SELECT *
-- FROM dbo.CategoryProducts cp WITH(NOLOCK)
-- WHERE ISNULL(cp.IsDeleted, 1) = 1
--) cp ON cp.ManufacturerID = p.ManufacturerID AND cp.ItemID = p.ItemID
WHERE p.ManufacturerID = #ManufacturerID
AND p.ModifiedOn > #tStamp

Using Table valued function the code

<pre>
I have 3 tables and one table valued function: EmpHistory,EmpRank,Emp and fnEmpRank.
The sample data are given as follows:
EmpHistory
EmpHistID EmpID RankID MonitorDate RankName
1 aba JPR 2008-10-06 Junior Prof
2 aba JPR 2009-11-07 Junior Prof
3 aba TERM 2012-2-08 Termoinated Prof
4 aba ASST 2012-6-22 lab Assistant
5 aba ASST 2012-7-2 Lab Assistant
6 aba TSST 2012-8-4 Terminated Assistant
EmpRank
RankID RankName
JPR Junior Professor
SPR Senior Professor
ASST Junior Assistant
SASST Senior Assistant
PL Principal
Employee
EmpID EmpStartDate
aba 2008-10-06
abc01 2007-09-23
sdh 2009-7-26
sbs 2012-2-8
The fnEmpRank function takes the emproleID and gives the employee history same as the empHistory Table. There is also empoyeerole table which has employeeroleid column.
Now my problem is: I want the second last professor rank of the employee i.e in this case I want Junior Professor row(i.e) 2nd row from emphistory table). Currntly my code is using emphistory table but now intead of that table I want to use fnEmpRank as it gives the same data. I am also giving the sample code.
select
a.EmpID,
a.StartDate,
J.RankID,
c.MonitorDate,
from dbo.vwEmployee A(nolock)
INNER join dbo.EmpHistory c(nolock) on c.Empid = a.EmpID
and c.EmpHistoryID = (select max(c1.EmpHistoryID)
from dbo.EmpHistory c1(nolock)
where c1.Empid = c.EmpID
and c1.MonitorDate =
(
I have 3 tables and one table valued function: EmpHistory,EmpRank,Emp and fnEmpRank.
The sample data are given as follows:
create table EmpHistory(
EmpHistID int,
EmpID varchar,
RankID varchar,
Monitordate Date,
Rankname varchar)
insert into EmpHistory
select 1,'aba','JPR','2008-10-6','Junior Professor'
insert into EmpHistory
select 2,'aba','JPR','2009-11-7','Junior Professor'
insert into EmpHistory
select 3,'aba','TERM','2012-2-8','Terminated Prof'
insert into EmpHistory
select 4,'aba','ASST','2012-6-22','Lab Assistant'
insert into EmpHistory
select 5,'aba','ASST','2012-7-2','Lab Assistant'
insert into EmpHistory
select 1,'aba','JPR','2012-8-4','Terminated Assistant'
create table EmpRank(
RankID varchar,
RankName varchar
)
insert into EmpRank
select 'JPR','Junior Professor'
insert into EmpRank
select 'SPR','Senior Professor'
insert into EmpRank
select 'ASST','Junior Assistant'
insert into EmpRank
select 'SASST','Senior Assistant'
insert into EmpRank
select 'PL','Principal'
create table Employee(
EmpID varchar,
EmpStartDate date
)
insert into Employee
select 'aba','2008-10-06'
insert into Employee
select 'abc01','2007-9-23'
insert into Employee
select 'sdh','2009-7-26'
insert into Employee
select 'sbs','2012-2-8'
The fnEmpRank function takes the emproleID and gives the employee history same as the empHistory Table. There is also empoyeerole table which has employeeroleid column.
Now my problem is: I want the second last professor rank of the employee i.e in this case I want Junior Professor row(i.e) 2nd row from emphistory table). Currntly my code is using emphistory table but now intead of that table I want to use fnEmpRank as it gives the same data. I am also giving the sample code.
select
a.EmpID,
a.StartDate,
J.RankID,
c.MonitorDate,
from dbo.vwEmployee A(nolock)
INNER join dbo.EmpHistory c(nolock) on c.Empid = a.EmpID
and c.EmpHistoryID = (select max(c1.EmpHistoryID)
from dbo.EmpHistory c1(nolock)
where c1.Empid = c.EmpID
and c1.MonitorDate =
(
SELECT MAX(C2.MonitorDate)
FROM dbo.EmpHistory C2
WHERE C2.EmpID = C1.EmpID
)
)
join dbo.EmpRank d(nolock) on d.RankID = a.RankID
left join dbo.EmpHistory f(nolock) on f.EmpID = a.EmpID
and f.EmpHistoryID = (select max(g.EmpHistoryID)
from dbo.EmpHistory g(nolock)
where g.EmpID = a.EmpID
AND G.RankID not like 'T%'
and g.EmpHistoryID < c.EmpHistoryID)
left join dbo.EmpRank h(nolock) on h.RankID = f.RankID
LEFT JOIN dbo.EmpHistory J(NOLOCK) ON J.EmpID = A.EmpID
AND J.EmpHistoryID = (
SELECT max(K.EmpHistoryID )
FROM dbo.EmpHistory K(NOLOCK)
WHERE K.EmpID = J.EmpID
AND K.AgentRankID NOT LIKE 'T%'
AND K.MonitorDate = (
SELECT max(M.MonitorDate )
FROM dbo.EmpHistory M(NOLOCK)
WHERE M.EmpID = J.EmpID
AND M.RankID NOT LIKE 'T%'
)
)
where
A.Prof=1
c.RankID like 'T%'
AND c.RankID <>'TSST'
AND A.StartDate is not null
Here there is one more problem: Even if the Employee is terminated from professor to Assitant, A.Prof values is still 1 and basically Assistant dont have the start dates but when professor are transformed to Assitant, they still contain the start date. How can I handle this in the code. Basically this code assumes that that if emp has the start date then he is the professor. Can any one help me?
SELECT MAX(C2.MonitorDate)
FROM dbo.EmpHistory C2
WHERE C2.EmpID = C1.EmpID
)
)
join dbo.EmpRank d(nolock) on d.RankID = a.RankID
left join dbo.EmpHistory f(nolock) on f.EmpID = a.EmpID
and f.EmpHistoryID = (select max(g.EmpHistoryID)
from dbo.EmpHistory g(nolock)
where g.EmpID = a.EmpID
AND G.RankID not like 'T%'
and g.EmpHistoryID < c.EmpHistoryID)
left join dbo.EmpRank h(nolock) on h.RankID = f.RankID
LEFT JOIN dbo.EmpHistory J(NOLOCK) ON J.EmpID = A.EmpID
AND J.EmpHistoryID = (
SELECT max(K.EmpHistoryID )
FROM dbo.EmpHistory K(NOLOCK)
WHERE K.EmpID = J.EmpID
AND K.AgentRankID NOT LIKE 'T%'
AND K.MonitorDate = (
SELECT max(M.MonitorDate )
FROM dbo.EmpHistory M(NOLOCK)
WHERE M.EmpID = J.EmpID
AND M.RankID NOT LIKE 'T%'
)
)
where
A.Prof=1
c.RankID like 'T%'
AND c.RankID <>'TSST'
AND A.StartDate is not null
Here there is one more problem: Even if the Employee is terminated from professor to Assitant, A.Prof values is still 1 and basically Assistant dont have the start dates but when professor are transformed to Assitant, they still contain the start date. How can I handle this in the code. Basically this code assumes that that if emp has the start date then he is the professor. Can any one help me?
</pre>
create fnemprank(#inputrankid int)
returns #result table(
EmpHistID int,
EmpID nvarchar,
RankID nvarchar,
MonitorDate date,
RankName nvarchar)
as
begin
insert into #result (EmpHistID,EmpID,RankID,MonitorDate,RankName)
select top 1 * from emphistory eh where eh.rankid=#inputrankid
order by eh.monitordate desc
return
end

Resources