I have been at this for some time and am frustrated. Below is the complete SQL statement I am trying to execute. Simply put, create a temp table from a UNION Select(s) statements.
I can run the SELECTs with the UNION just fine. I can run the separate SELECTS just fine. I can run separate INSERT INTOs just fine. The moment I add an INSERT INTO SELECT * FROM (...) at the top and close it at the bottom I get a syntax error:
Msg 102, Level 15, State 1, Line 75
Incorrect syntax near ')'.
I was hoping this would be simple, but I tried everything I know to get this to work, and cannot. is there something, perhaps with the UNION that creates the syntax error?
INSERT INTO #Tmp6 SELECT * FROM
(
SELECT
[ItemStatus]
,[Item_Number]
,[Item_Name]
,[Default_Sales_Name]
,[Special_Order_Item]
,[Returnable]
,[Return_Number_Of_Days]
,[Is_Drop_Ship]
,[Is_JIT]
,[Vendor_Name]
,[Vendor_Number]
,[Default_Sales_Price]
,[Cost_Of_Goods]
,[Purchase_Cost]
,[Additional_Cost1_Text]
,[Additional_Cost1_Value]
,[Additional_Cost2_Text]
,[Additional_Cost2_Value]
,[Additional_Cost3_Text]
,[Additional_Cost3_Value]
,[UPC_Value]
,[Weight]
,[DimWeight]
,[Discontinued_Date]
,[Personalization_Template_Number]
,[Harmonized_Code]
,[Base_Category]
,[Sub_Category]
,[End_Category]
,[RowID]
FROM [dbo].[RAIProductsStg] p
WHERE ItemStatus <> 'Discontinued' OR
p.Item_Number IN (SELECT i.Item_Number FROM RAIInventoryStg i WHERE p.Item_Number = i.Item_Number AND Quantity > 0)
UNION
SELECT
[ItemStatus]
,[Item_Number]
,[Item_Name]
,[Default_Sales_Name]
,[Special_Order_Item]
,[Returnable]
,[Return_Number_Of_Days]
,[Is_Drop_Ship]
,[Is_JIT]
,[Vendor_Name]
,[Vendor_Number]
,[Default_Sales_Price]
,[Cost_Of_Goods]
,[Purchase_Cost]
,[Additional_Cost1_Text]
,[Additional_Cost1_Value]
,[Additional_Cost2_Text]
,[Additional_Cost2_Value]
,[Additional_Cost3_Text]
,[Additional_Cost3_Value]
,[UPC_Value]
,[Weight]
,[DimWeight]
,[Discontinued_Date]
,[Personalization_Template_Number]
,[Harmonized_Code]
,[Base_Category]
,[Sub_Category]
,[End_Category]
,[RowID]
FROM [dbo].[RAIProductsStg] p
LEFT JOIN RAIParentChildStg pc ON p.Item_Number = pc.ParentItemNumber
WHERE(LEN(p.Item_Number) = 6 AND p.ItemStatus = 'Discontinued') AND
(pc.ChildItemNumber IN
(SELECT i.Item_Number FROM RAIInventoryStg i
WHERE pc.ChildItemNumber = i.Item_Number AND i.Quantity > 0))
)
Please try this. Put alias after last bracket.
INSERT INTO #Tmp6
SELECT * FROM
(
SELECT
[ItemStatus]
,[Item_Number]
,[Item_Name]
,[Default_Sales_Name]
,[Special_Order_Item]
,[Returnable]
,[Return_Number_Of_Days]
,[Is_Drop_Ship]
,[Is_JIT]
,[Vendor_Name]
,[Vendor_Number]
,[Default_Sales_Price]
,[Cost_Of_Goods]
,[Purchase_Cost]
,[Additional_Cost1_Text]
,[Additional_Cost1_Value]
,[Additional_Cost2_Text]
,[Additional_Cost2_Value]
,[Additional_Cost3_Text]
,[Additional_Cost3_Value]
,[UPC_Value]
,[Weight]
,[DimWeight]
,[Discontinued_Date]
,[Personalization_Template_Number]
,[Harmonized_Code]
,[Base_Category]
,[Sub_Category]
,[End_Category]
,[RowID]
FROM [dbo].[RAIProductsStg] p
WHERE ItemStatus <> 'Discontinued' OR
p.Item_Number IN (SELECT i.Item_Number FROM RAIInventoryStg i WHERE p.Item_Number = i.Item_Number AND Quantity > 0)
UNION
SELECT
[ItemStatus]
,[Item_Number]
,[Item_Name]
,[Default_Sales_Name]
,[Special_Order_Item]
,[Returnable]
,[Return_Number_Of_Days]
,[Is_Drop_Ship]
,[Is_JIT]
,[Vendor_Name]
,[Vendor_Number]
,[Default_Sales_Price]
,[Cost_Of_Goods]
,[Purchase_Cost]
,[Additional_Cost1_Text]
,[Additional_Cost1_Value]
,[Additional_Cost2_Text]
,[Additional_Cost2_Value]
,[Additional_Cost3_Text]
,[Additional_Cost3_Value]
,[UPC_Value]
,[Weight]
,[DimWeight]
,[Discontinued_Date]
,[Personalization_Template_Number]
,[Harmonized_Code]
,[Base_Category]
,[Sub_Category]
,[End_Category]
,[RowID]
FROM [dbo].[RAIProductsStg] p
LEFT JOIN RAIParentChildStg pc ON p.Item_Number = pc.ParentItemNumber
WHERE(LEN(p.Item_Number) = 6 AND p.ItemStatus = 'Discontinued') AND
(pc.ChildItemNumber IN
(SELECT i.Item_Number FROM RAIInventoryStg i
WHERE pc.ChildItemNumber = i.Item_Number AND i.Quantity > 0))
)c
Place the bracket after the second select statement. That should do it.
INSERT INTO TableA
(
SELECT A, B, C
FROM TableB
UNION
SELECT D, E, F
FROM TableC
)
Related
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;
;
I'm obviously new to this and I need some help. I have this code in SQL Server Management Studio.
The error that I get is
Msg 156, Level 15, State 1, Line 38
Incorrect syntax near the keyword 'IF'
If I execute direct select statement instead of using "If" the query is successfully executed.
Please point out what I am missing and where is my mistake.
Thanks a lot.
declare #dateFrom [date] = cast(dateadd(day, -7, getdate()) as [date]);
declare #dateTo [date] = cast(dateadd(day, 28, getdate()) as [date]);
declare #prTypeCode [varchar](10) = null;
declare #ExcludeA [bit] = 0 ;
declare #ExcludeB [bit] = 0;
;with distribution as
(
select *
from [schema1].[Table1]
),
product as
(
select *
from [schema1].[Product]
),
fint as
(
select
*,
(case when CHARINDEX('0%', FIN_ CODE) > 0 then 1 else 0 end) as ZFlag
from [schema1].[FinTab]
),
deal as
(
select
*,
case when (AG_ID = 5 or DE_ID = 6) then 1
else 0 end as Ex_flag
from
[P_ BASE1].[ schema2].[table3]
),
dealersn as
(
select distinct *
from [P_ BASE1].[ schema2].[table4]
),
regionN as
(
select distinct *
from [P_ BASE1].[ schema2].[table5]
),
final as
(
select
d.PRODUCT_CODE, p.PR_NAME, p.PR_TYPE_CODE, p.PR_ACTIVE,
d.FIN_TABLE_CODE, ft.FT_NAME, ft.FT_ACTIVE,
cast(d.SND_TO_DATE as [date]) as SND_TO_DATE,
count(d.SN_ID) as SHOP_COUNT,
min(ft.ZFlag) as ZFlag,
min(ds.Ex_flag) as ExFlag, dn.SND_FULLNAME,rn.REG_NAME
from
distribution d
left outer join
product p on p.PRODUCT_CODE = d.PRODUCT_CODE
left outer join
fint ft on ft. FIN_ CODE = FIN_ CODE
left outer join
deal as ds On d.SN_ID = ds.SHOP_ID
left outer join
dealersn as dn on d.SN_ID = dn.SN_DATA_ID
left outer join
regionN as rn ON ds.REGION_ID = rn.REGION_ID
where
d.SND_TO_DATE between #dateFrom and #dateTo
and (#prTypeCode is null or p.PR_TYPE_CODE = #prTypeCode)
group by
rn.REG_NAME, ds.REGION_ID, ds.SHOP_ID, d.PRODUCT_CODE, p.PR_NAME,
p.PR_TYPE_CODE, p.PR_ACTIVE, d.FIN_TABLE_CODE, ft.FT_NAME,
ft.FT_ACTIVE, d.SND_TO_DATE,dn.SND_FULLNAME
)
IF (#ZeroPercent = 0 AND #LargeChainsOrTushev = 0)
BEGIN
SELECT DISTINCT *
FROM final
WHERE ZFlag = 0 AND ExFlag = 0
END
ELSE
IF #ZeroPercent = 1 AND #LargeChainsOrTushev = 0
BEGIN
SELECT DISTINCT *
FROM final
WHERE ZFlag = 1 AND ExFlag = 0
END
ELSE IF #ZeroPercent = 0 AND #LargeChainsOrTushev = 1
BEGIN
SELECT DISTINCT *
FROM final
WHERE ZFlag = 0 AND ExFlag = 1
END
ELSE
BEGIN
SELECT DISTINCT *
FROM final
END
You have a with statement that "defines" a bunch of tables, the last of which is called final. This is called a CTE (Common Table Expression). You can use CTEs for many reasons, but the important thing is, you have to use the CTE in a query. Instead you define the CTE and then...do nothing.
If you put a line like this:
select * from final
just after the CTE (before the IF), it will run.
(Edited from the original).
In plpgsql, (PostgreSQL 9.2), I have a function defined as:
CREATE OR REPLACE FUNCTION test (patient_recid integer, tencounter timestamp without time zone)
RETURNS SETOF view_dx AS
$BODY$
#variable_conflict use_column
DECLARE
r view_dx%rowtype;
BEGIN
FOR r IN
With person AS (
select ....
)
, alldx AS (
select ....
)
............
select ... from first cte
union
select ... from second cte
union
etc., etc.,
LOOP
r.tposted = ( .
With person AS (
... SAME AS ABOVE,
alldx AS (
... SAME AS ABOVE,
)
select max(b.tposted)
from alldx b
where r.cicd9 = b.code and r.cdesc = b.cdesc);
r.treated = (
With person AS (
........SAME AS ABOVE )
, alldx AS (
........SAME AS ABOVE
)
select ...);
r.resolved = (
With person AS (
select p.chart_recid as recid
from patients p
where p.recid = patient_recid
)
...etc, etc,
RETURN NEXT r;
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION test(integer, timestamp without time zone)
OWNER TO postgres;
Edit: Essentially, I have multiple cte's defined which work well in the "For r IN" section of code with multiple unions, but when executing the LOOP...END LOOP section, each CTE needs to be redefined with each SELECT statement. Is there a good way to avoid multiple definitions of the same CTE?
Or is there a better (i.e., faster) way of doing this.
All suggestions are most welcome and appreciated.
TIA
[this is not an answer (too little information, too large program), but a hint for rewriting the stacked CTE.]
The members of the union all appear to be based on select b.* from alldx b, all with a few different extra conditions, mostly based on the existance of other tuples within the same CTE. My suggestion is to unify these, replacing them by boolean flags, as in:
WITH person AS (
SELECT p.chart_recid as recid
FROM patients p
WHERE p.recid = patient_recid
)
, alldx AS (
SELECT d.tposted, d.treated, d.resolved, d.recid as dx_recid, d.pmh, d.icd9_recid
, i.code, i.cdesc, i.chronic
FROM dx d
JOIN icd9 i ON d.icd9_recid = i.recid
JOIN person p ON d.chart_recid = p.recid
WHERE d.tposted::date <= tencounter::date
)
SELECT uni.tposted, uni.treated, uni.resolved, uni.dx_recid, uni.pmh, uni.icd9_recid
, uni.code, uni.cdesc, uni.chronic
, (uni.tposted::date = tencounter::date
) AS is_dx_at_encounter -- bitfield
, EXISTS ( -- a record from a more recent date has resolved this problem.
SELECT 1
FROM alldx x
WHERE x.resolved = true
AND uni.code = x.code AND uni.cdesc = x.cdesc AND uni.tposted = x.tposted
AND x.tposted >= uni.tposted
) AS dx_resolved -- bitfield
, EXISTS ( -- a record from a more recent date has resolved this problem.
SELECT 1
FROM alldx x
WHERE x.resolved = false
AND uni.code = x.code AND uni.cdesc = x.cdesc AND uni.tposted = x.tposted
AND x.tposted > uni.tposted
) AS dx_recurred -- bitfield
, EXISTS ( SELECT * from alldx x where x.chronic = true
AND uni.code = x.code AND uni.cdesc = x.cdesc
) AS dx_chronic -- bitfield
-- etcetera
FROM alldx uni
;
The person CTE could probably be incorporated, too.
and maybe you don't even need the final loop
but you'll have to find out which combination(s) of the resulting bitfields will be needed.
the UNION (without ALL) in the original is a terrible beast: it collects all the results from the union parts, but has to remove duplicates. This will probably introduce a sort-step, since CTE-references tend to hide their key fields or implied ordering from the calling query.
As far as I can tell, CTE's defined before the LOOP do not transfer to the LOOP itself. However, a temporary table can be defined in the BEGIN block which is available in the LOOP block. The following solution runs 50 times faster then my original code. Anybody have a better approach?
CREATE OR REPLACE FUNCTION test2 (patient_recid integer, tencounter timestamp without time zone)
RETURNS SETOF view_dx AS
$BODY$
#variable_conflict use_column
DECLARE
r view_dx%rowtype;
BEGIN
-- create table can only be created in the BEGIN block
Create temp table all_dx ON COMMIT DROP AS
With person AS (
select p.chart_recid as recid
from patients p
where p.recid = patient_recid
)
, alldx AS (
select d.tposted, d.treated, d.resolved, d.recid as dx_recid, d.pmh, d.icd9_recid, i.code, i.cdesc, i.chronic
from dx d
join icd9 i on (d.icd9_recid = i.recid)
join person p on (d.chart_recid = p.recid)
where d.tposted::date <= tencounter::date
)
select * from alldx order by tposted desc;
-- will loop through all the records produced by the unions and assign tposted, pmh, chronic, etc...
FOR r IN
With
dx_at_encounter AS ( -- get all diagnosis at time of encounter
select code, cdesc from all_dx a
where a.tposted::date = tencounter::date
)
, dx_resolved AS ( -- get most recent date of every resolved problem.
select b.* from all_dx b
join (
select a.code, a.cdesc , max(tposted) as tposted
from all_dx a
where a.resolved = true
group by code,cdesc) j
on (b.code = j.code and b.cdesc = j.cdesc and b.tposted = j.tposted)
)
, never_resolved AS ( -- get all problems that have never been resolved before time of encounter.
-- "not exists" is applied to each select output row AFTER the output row b.* is formed.
select b.code, b.cdesc from all_dx b
where not exists
(select 1
from dx_resolved d
where b.code = d.code and b.cdesc = d.cdesc)
)
, recurrent AS ( -- get all recurrent problems. (Problems that are now current after being resolved).
select b.code, b.cdesc
from all_dx b
join dx_resolved r on (b.cdesc = r.cdesc and b.tposted::date > r.tposted::date )
where (b.resolved is null or b.resolved = false)
)
, chronic_dx AS (
select b.code, b.cdesc
from all_dx b
where b.chronic = true
)
-- all diagnosis at time of encounter
select a.code,
a.cdesc
from dx_at_encounter a
union
-- all recurrent problems
select
a.code,
a.cdesc
from recurrent a
union
-- all problems that have never been resolved
select
a.code,
a.cdesc
from never_resolved a
union
--all chonic problems
select
a.code,
a.cdesc
from chronic_dx a
-- LOOP goes to END LOOP which returns back to LOOP to process each of the result records from the unions.
LOOP
r.tposted = ( -- get most recent useage of a diagnosis.
select max(b.tposted)
from all_dx b
where r.cicd9 = b.code and r.cdesc = b.cdesc);
r.treated = (
select b.treated from all_dx b
where b.tposted = r.tposted and b.code = r.cicd9 and b.cdesc = r.cdesc);
r.resolved = (
select b.resolved from all_dx b
where b.tposted = r.tposted and b.code = r.cicd9 and b.cdesc = r.cdesc);
r.pmh = (
select distinct true
from all_dx b
where
b.pmh = true and
b.code = r.cicd9 and
b.cdesc = r.cdesc );
r.chronic = (
select distinct true
from all_dx b
where
b.chronic = true and
b.code = r.cicd9 and
b.cdesc = r.cdesc);
RETURN NEXT r; -- return current row of SELECT
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION test2(integer, timestamp without time zone)
OWNER TO postgres;
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
Below is a complete query I have and the ultimate aim is to update the claim table. But it should be only one statement without any subquery, only joins are allowed because I am going to run this in an appliance which won't support subquery:
DECLARE #DecWdrwn as TABLE(CtryId smallint, CmId int, DecWdrwnDt int);
WITH s AS
(
SELECT
Ctryid,CmId,Dt,
ISNULL((
SELECT max(CmHistDtTmId)
FROM ClaimHistory l
WHERE St = 3
AND l.Ctryid = c.Ctryid
AND l.CmId = c.CmId)
, 0) MaxDec,
ISNULL((
SELECT max(CmHistDtTmId)
FROM ClaimHistory l
WHERE St = 7
AND l.Ctryid = c.Ctryid
AND l.CmId = c.CmId)
, 0) MaxSet
FROM
ClaimHistory c
WHERE
St =3
)
INSERT INTO #DecWdrwn
SELECT CtryId, CmId, Max(Dt) DecDt
FROM s
WHERE MaxSet > MaxDec
GROUP BY CtryId,CmId
Your response is much appreciated...
UPDATE Claims
SET CmDclnWdwnDt = (
SELECT DecWdrwnDt
FROM #DecWdrwn d
WHERE d.CmId = Claims.CmId
AND d.CtryId = Claims.CtryId
)
WHERE EXISTS (
SELECT *
FROM #DecWdrwn d
WHERE d.CmId = Claims.CmId
AND d.CtryId = Claims.CtryId
)
Please try INNER JOIN Update:
UPDATE a
SET a.CmDclnWdwnDt = b.DecWdrwnDt
FROM Claims a, #DecWdrwn b
WHERE a.CmId = b.CmId AND
a.CtryId =b.CtryId