Must declare the scalar variable SQL Server? - sql

SELECT CD.CartId
,PR.Name
,PR.SKU
,CD.Quantity
,CD.Price
,CD.Total
,CD.IsAddedFromWidget
,CD.WidgetSlotLabel
,CD.AddToCartDate
,CO.UpdatedDate AS [CheckoutDate]
,CD.PurchaseDate {from [Tracking].[CartDetail] CD
INNER JOIN [Tracking].[Cart] C ON CD.CartId = C.Id
INNER JOIN [Tracking].[Product] PR ON CD.ProductId = PR.Id
INNER JOIN [Tracking].[Checkout] CO ON C.$NODE_ID = CO.$TO_ID
WHERE C.WebsiteId = #Websited
AND C.STATUS = 20
AND CD.PurchaseDate >= #FromDate
AND CD.PurchaseDate <= #ToDate
ORDER BY CD.PurchaseDate DESC
,CD.CartId DESC}
However, I am getting the error:
Must declare the scalar variable "#WebsiteID".

Here is an example of what your declarations might look like.
DECLARE #WebsiteID uniqueidentifier = NEWID()
,#FromDate DATETIME = GETDATE() - 1
,#ToDate DATETIME = GETDATE()
SELECT CD.CartId
,PR.Name
,PR.SKU
,CD.Quantity
,CD.Price
,CD.Total
,CD.IsAddedFromWidget
,CD.WidgetSlotLabel
,CD.AddToCartDate
,CO.UpdatedDate AS [CheckoutDate]
,CD.PurchaseDate
FROM [Tracking].[CartDetail] CD
INNER JOIN [Tracking].[Cart] C ON CD.CartId = C.Id
INNER JOIN [Tracking].[Product] PR ON CD.ProductId = PR.Id
INNER JOIN [Tracking].[Checkout] CO ON C.$NODE_ID = CO.$TO_ID
WHERE C.WebsiteId = #WebsiteID
AND C.STATUS = 20
AND CD.PurchaseDate >= #FromDate
AND CD.PurchaseDate <= #ToDate
ORDER BY CD.PurchaseDate DESC
,CD.CartId DESC
Also, it appears to me that #Websited is a typo, so I've used #WebsiteID.
I've also removed the invalid { } braces from your code.
Additionally, the column names $NODE_ID and $TO_ID look a little weird to me. (The usage of $ is what I am talking about).

Related

scalar variable error after it has been declared

I'm running Microsoft SQL Server 17.7 and I keep getting an error message when trying to filter my data set by a date range with a where clause using a scalar variable. I declared both variables but I continue to get this error message "Must declare the scalar variable "#startDate". I'm guessing I'm not declaring the scalar variable correctly. Please assist.
DECLARE #MatterList NVARCHAR(100) = '(21940-00035)'
declare #startDate datetime = '1/1/2012'
declare #endDate datetime = '6/30/2015'
SELECT #MatterList = NULL
WHERE #MatterList = ''
DROP TABLE IF EXISTS #listMatter
DROP TABLE IF EXISTS #Matterlist
CREATE TABLE #MatterList (rowid int identity, MatterNumber nvarchar(20))
CREATE INDEX tMatterListIndex_MatterNumber on #MatterList (MatterNumber)
select value into #listMatter from
string_split(replace(replace(replace(#MatterList,'(',''),')',''), ' ' , ''), ',')
Insert into #MatterList (MatterNumber)
select m.Number as MatterNumber
from #listMatter lm
inner join Matter m with (nolock) on lm.value = m.Number
where m.Number not in (select matterNumber from #MatterList)
If OBJECT_ID('tempdb..#fees_detail') is not NULL drop table #fees_detail
GO
SELECT DISTINCT 'Fees' AS [type],
t.code AS tudef2,
tc.PostDate AS bfindt,
tc.IsActive AS isActive,
tc.IsNoCharge AS isNoCharge,
m.OpenDate AS mopendt,
m.CloseDate AS mclosedt,
m.ContactInfo AS 'matter_contact',
a.DESCRIPTION AS 'matter_arrangement',
m.BillingInstruc AS 'billing_instructions',
m.Comments AS 'terms',
m.Number AS 'matter_id',
c.DisplayName AS 'client_name',
m.DisplayName AS 'matt_desc',
m.Narrative_UnformattedText AS 'matt_nar',
btk.Number AS 'batty_id',
btk.DisplayName AS 'batty_name',
tk.Number AS 'tk_id',
tk.DisplayName AS 'tk_name',
td.HireDate AS 'tkemdate',
title.DESCRIPTION AS 'tktitle',
htitle.DESCRIPTION AS 'htitle',
CASE htitle.DESCRIPTION
WHEN 'partner'
THEN 1
WHEN 'associate'
THEN 2
WHEN 'summer assoc.'
THEN 3
WHEN 'staff counsel'
THEN 4
WHEN 'paralegal'
THEN 5
WHEN 'als'
THEN 6
WHEN 'CSS admin'
THEN 7
WHEN 'legal graphics'
THEN 8
WHEN 'library'
THEN 9
WHEN 'case clerks'
THEN 10
WHEN 'lit analyst'
THEN 11
ELSE 12
END AS 'tktitle_sort',
d.DESCRIPTION AS 'mdept',
pg.DESCRIPTION AS 'mprac',
o.DESCRIPTION AS 'mloc',
tc.TimeIndex AS 't_index',
tc.WorkDate AS 'worked_date',
CONVERT(VARCHAR(6),tc.workdate,112) AS 'worked_period',
tc.WorkHrs AS 'tworkhrs',
tc.WorkRate AS 'tworkrt',
tc.WorkAmt AS 'tworkdol',
tc.WIPRemoveDate AS 'tbilldt',
tc.WIPHrs AS 'tbillhrs',
tc.WIPRate AS 'tbillrt',
tc.WIPAmt AS 'tbilldol',
tc.Narrative_UnformattedText AS 'time_desc',
'' AS 'ccode',
'' AS 'codesc1',
CASE
WHEN tc.IsNB = 1
THEN 0.00
ELSE tc.WIPAmt - tc.WorkAmt
END AS 'adj'
INTO #fees_detail
FROM timecard tc WITH (NOLOCK)
INNER JOIN matter AS m WITH (NOLOCK)
ON tc.matter = m.mattindex
INNER JOIN #MatterList AS tm
ON m.Number = tm.MatterNumber
INNER JOIN mattdate AS md WITH (NOLOCK)
ON m.MattIndex = md.MatterLkUp
AND CONVERT(DATE,GETDATE()) BETWEEN md.NxStartDate AND md.NxEndDate
INNER JOIN client AS c WITH (NOLOCK)
ON m.client = c.ClientIndex
INNER JOIN PracticeGroup AS pg WITH (NOLOCK)
ON md.PracticeGroup = pg.Code
INNER JOIN Department AS d WITH (NOLOCK)
ON md.Department = d.Code
INNER JOIN Arrangement AS a WITH (NOLOCK)
ON md.Arrangement = a.Code
INNER JOIN Office AS o WITH (NOLOCK)
ON md.Office = o.Code
INNER JOIN Timekeeper AS tk WITH (NOLOCK)
ON tc.Timekeeper = tk.TkprIndex
INNER JOIN TkprDate AS td WITH (NOLOCK)
ON tk.TkprIndex = td.TimekeeperLkUp
AND CONVERT(DATE,GETDATE()) BETWEEN td.NxStartDate AND td.NxEndDate
INNER JOIN TkprDate AS htd WITH (NOLOCK)
ON tk.TkprIndex = htd.TimekeeperLkUp
AND tc.WorkDate BETWEEN htd.NxStartDate AND htd.NxEndDate
INNER JOIN Timekeeper AS btk WITH (NOLOCK)
ON md.BillTkpr = btk.TkprIndex
INNER JOIN title WITH (NOLOCK)
ON td.title = title.code
INNER JOIN title AS htitle WITH (NOLOCK)
ON htd.title = htitle.code
LEFT OUTER JOIN task AS t WITH (NOLOCK)
ON tc.Task = t.TaskID
Where tc.WorkDate between #startDate and #enddate
ORDER BY m.Number, tc.WorkDate, tc.TimeIndex
SELECT
[type], tudef2, bfindt, isActive, isNoCharge, mopendt, mclosedt, matter_contact,
matter_arrangement, billing_instructions, terms, matter_id, client_name, matt_desc, matt_nar,
batty_id, batty_name, tk_id, tk_name, tkemdate, tktitle, htitle, tktitle_sort, mdept, mprac,
mloc, t_index, worked_date, worked_period, tworkhrs, tworkrt, tworkdol, tbilldt, tbillhrs,
tbillrt, tbilldol, time_desc, ccode, codesc1, adj
FROM #fees_detail
ORDER BY 29
GO flags the end of a batch of statements, i.e. everything from the beginning of the file (or the previous GO) is sent as one batch, and executed; this was probably ok, then everything following GO until the end of the file or the next GO is sent and executed, when this happened your declarations were already gone (not part of this batch. Remove GO.

How to return an extra column in a sub query that is a UNION

I want to somehow get the Promotions Id from the second select in a UNION which is a sub query that brings back one column.
Is it somehow possible to achieve this or will I have to duplicate the 2nd query somehow again?
Updated
So, basically this code will get a Promotion Price from an older Table in the same Database and then it will UNION it to a new Promotions Table and select the best or lowest price from the two, but the newer Promotion Table has a Promotion Id (P.Id) which I need to return.
Additional Unrelated Info
The DateValidFrom and DateValidTo is of type Datetime because the Promotion can have a start and end date with a specific time.
Expected Outcome
I want to return the Promotions Id which is P.Id from the Promotions Table.
ALTER FUNCTION [dbo].[GetCustomerPricingForProduct] (#StockParentId int,
#CustomerCode varchar(30),
#PricingDate date,
#ChannelID int,
#QTY int,
#CustCategoryNo int,
#PriceType int,
#CustomerDealerType int)
RETURNS table
AS
RETURN (SELECT ISNULL(F.Price, ISNULL(R.SellingPrice, 0)) AS StandardPrice,
(SELECT DiscountLines.amount
FROM Customers
INNER JOIN CustDiscounts ON Customers.pricelist = CustDiscounts.no
INNER JOIN DiscountLines ON CustDiscounts.no = DiscountLines.no
INNER JOIN FinGoodsParent FP ON FP.Id = DiscountLines.FinGoods_ID
WHERE Customer_Code = #CustomerCode
AND CONVERT(date, CustDiscounts.startdate) <= #PricingDate
AND CONVERT(date, CustDiscounts.enddate) >= #PricingDate
AND DiscountLines.TYPE = #PriceType
AND FP.Id = #StockParentId) AS PricelistPrice,
(SELECT TOP 1
Pricing
FROM (SELECT Pricing
FROM PROMGEN
INNER JOIN FinGoodsParent FP ON FP.Id = PROMGEN.FinGoods_ID
INNER JOIN PromCateg ON PROMGEN.No = PromCateg.PromGen_No
INNER JOIN PromGen_Channels ON PROMGEN.No = PromGen_Channels.PromGen_No
INNER JOIN Channels ON PromGen_Channels.Channels_Id = Channels.Id
WHERE PROMGEN.MINQUANT <= #QTY
AND #PricingDate >= CONVERT(date, PROMGEN.START_DATE)
AND #PricingDate <= CONVERT(date, PROMGEN.END_DATE)
AND Channels_Id = #ChannelID
AND PromCateg.CustCateg_No = #CustCategoryNo
AND FP.Id = #StockParentId
AND PROMGEN.TYPE = #PriceType
UNION
SELECT MIN(SP_P.PricingRuleTypeAmount) AS Pricing
FROM StockParent_Promotions SP_P
INNER JOIN Promotions P ON P.Id = SP_P.Promotions_Id
INNER JOIN Promotions_Channels PC ON PC.Promotions_Id = P.Id
INNER JOIN StockParent SP ON SP_P.StockParent_Id = SP.Id
INNER JOIN Promotions_CustCateg PCC ON PCC.Promotions_Id = P.Id
INNER JOIN CUSTCATEG CC ON CC.NO = PCC.CustCateg_No
WHERE SP_P.MinPurchaseQuantity <= #QTY
AND #PricingDate >= CONVERT(date, P.DateValidFrom)
AND #PricingDate <= CONVERT(date, P.DateValidTo)
AND Channels_Id = #ChannelID
AND PCC.CustCateg_No = #CustCategoryNo
AND SP.Id = #StockParentId
AND SP_P.PricingRuleType = #PriceType
AND ((P.IsPromotionForEndUsers = 1
AND #CustomerDealerType = 1)
OR (P.IsPromotionForDealers = 1
AND #CustomerDealerType = 0))
AND P.IsDeleted = 0) OldAndNewPromotions
WHERE Pricing IS NOT NULL
ORDER BY Pricing ASC) AS PromotionPrice
FROM StockParent
LEFT JOIN Fingoods F ON F.Id = StockParent.ID
LEFT JOIN RAWMAT R ON R.Id = StockParent.ID
WHERE StockParent.Id = #StockParentId);

UPDATE all records from existing SELECT query

I have query to select data from related tables.
SELECT
s.id,
CASE
WHEN count(DISTINCT e.id) <> 0
THEN count(DISTINCT o.id) / count(DISTINCT e.id)
END OrdersAverageNumber
FROM
[School] s
JOIN
[SchoolStore] ss ON ss.SchoolId = s.Id
JOIN
[Event] e ON e.SchoolId = ss.SchoolId
AND e.IsDeleted = 0
AND e.Status = 1
AND e.Date >= #startDate
AND e.Date <= #endDate
JOIN
[Order] o ON o.EventId = e.id
AND o.OrderStatus = 1
AND o.CreatedDate >= #startDate
AND o.CreatedDate <= #endDate
GROUP BY
s.id;
But I can't understand what I need to change to update all OrdersAverageNumber records in School table with values from selection above.
You can use update:
with q as (< your query here >)
update s
set OrdersAverageNumber = q.OrdersAverageNumber
from school s join
q
on s.id = q.id;

Any Alternatives to Unions in SQL Server?

So, I'm in the process of creating a query that will bring back all the data I need.
Here's my query:
Declare #StartDate datetime
Set #StartDate = '2/1/2018'
Declare #EndDate datetime
Set #EndDate = '4/5/2018'
Declare #UserID int
Set #UserId = '153056'
;with EntData as
(
select
distinct (Entity_ID), a.user_ID, c.User_OrganizationalUnitID
from
ViewMgmt as a
ViewConsole b on a.Role_ID = b.RoleID
ViewUsers c on a.User_ID = c.UserID
where
b.RoleID in ( 53354666, 5363960) and
a.User_ID = #UserID and
a.Entity_ID <> 6912276036227
)
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227 or a.UI <> 1414)
and a1.IsHidden = 0 and a.UCS <> 13
UNION
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData g on a.UI = g.OID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and a.UI <> 6912276036227
and a.UI = 1414
and (c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561))
and a1.Hidden = 0 and a.UCS <> 13
Originally, the first part of the union was all that I had, but someone wanted to see extra data SPECIFICALLY for one ID (a.UI = 1414). I didn't want to bring back more data for all the UI's in the system, so I made a union to bring back extra data specifically in one UI. The data that I want is coming back; however, now, instead of loading within a minute, the query can take upwards of 4 minutes to load (versus 30-40 seconds for the first SELECT statement). I've been wrestling with this code for a while now and I'm ready to get it working efficiently.
I was trying to think if there was a way to do that last join (inner join EntData g on a.UI = g.OID in the last part of the union, rather than having to tack on a completely separate SELECT statement) only when the UI equals 1414, but I don't think that's possible. I tried implementing that last join into the first SELECT, but it did not run. I'm still a novice with SQL, so any help would greatly be appreciated.
Thank You.
Your joint queries are almost same. Try to join them and make one query from them. I think this query should return same result. But will include duplicate rows if there are.
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227)
and a1.IsHidden = 0 and a.UCS <> 13
and 1 = case
when a.UI = 1414
case
when c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561) then 1
else 0
end
else 1
end
I refactored and added some notes.
DECLARE #StartDate datetime
SET #StartDate = '2018-02-01' --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE #EndDate datetime
SET #EndDate = '2018-04-05' --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE #UserID int
SET #UserId = 153056 --- Remove single quotes. You're assigning a string to an int.
; WITH EntData AS (
SELECT DISTINCT Entity_ID , OID /* This needs to be included for later JOIN. Remove the other columns you don't use. */
FROM ViewMgmt a --- USE ANSI-92 syntax. Pretty please.
INNER JOIN ViewConsole b on a.Role_ID = b.RoleID
AND b.RoleID in ( 53354666, 5363960 )
INNER JOIN ViewUsers c on a.User_ID = c.UserID
WHERE
a.User_ID = #UserID
AND a.Entity_ID <> 6912276036227
)
, UnionedQueries AS ( -- Combine the common parts of the UNIONed queries into a second CTE for reuse.
SELECT a.User_ID, a.User_Name, a.UOName
, b.C_OID
, c.OName
, d.CID
, e.Affected
, a.UI -- Added for UNION
, a.CI_D -- Added for UNION
FROM view.a a
INNER JOIN view_Cool.a1 a2 ON a.User_ID = a1.UserID
AND a.CI_D = a1.CID
AND a1.IsHidden = 0 --- Move this filter into the INNER JOIN. It will reduce the JOINed resultset.
INNER JOIN view_New.b b ON a.CI_D = b.C_ID
LEFT JOIN view_Large.c c ON b.C_OID = c.OID
/* These JOINs are connecting across multiple tables. Make sure it's returning what you think it is how it should be. */
LEFT JOIN view_Small.d d ON a.CI_D = d.CID
LEFT JOIN view_Old.e e ON d.Cert_ID = e.CI_D
AND a.User_ID = e.User_ID
WHERE (
( a.ExpirationDate BETWEEN #StartDate AND #EndDate ) /* ??? and a.ExpirationDate = a.ExpirationDate ??? Typo? What was this supposed to do? */
OR
( a.ExpirationDate IS NULL ) --If this is checking for NULL, it won't be BETWEEN #StartDate and #EndDate
--- These two conditions could be combined as ISNULL(a.ExpirationDate,#StartDate), but that is very micro-optimization.
)
and a.UI NOT IN ( 6912276036227, 1414 ) -- This is functionally the same as using two <>s, just easier to follow.
and a.UCS <> 13
)
/* Now that the common query is already run, we can just use those results to get our final UNION */
SELECT u1.User_ID, u1.User_Name, u1.UOName, u1.C_OID, u1.OName, u1.CID, u1.Affected
FROM UnionedQueries u1
INNER JOIN EntData ON u1.C_OID = EntData.Entity_ID -- This JOIN seems to be the only significant difference between the two queries.
UNION
SELECT u2.User_ID, u2.User_Name, u2.UOName, u2.C_OID, u2.OName, u2.CID, u2.Affected
FROM UnionedQueries u2
INNER JOIN EntData g on u2.UI = g.OID -- This JOIN seems to be the only significant difference between the two queries.
WHERE u2.UI = 1414
AND (
u2.OName LIKE '%VXA%'
OR u2.OName LIKE '%Amazon%'
OR u2.CI_D IN ( 414,4561 )
)
;
Note: This will need to be tested. I don't know how much data the EntData CTE filters the queries, so excluding it to the end may result in a much larger dataset in the main queries.

how to rewrite query of temp table to subquery or join in sql

I need help Please.I have a query that was inserted into two different temp table. How can i rewrite the query again to avoid the use of temp table.
For example,
declare #sdate as datetime
declare #edate as datetime
set #sdate = '01-Apr-2016 00:00:00'
set #edate = '31-Mar-2017 23:59:59'
/*Falls*/
Select
DISTINCT
R.ID
,C.EmpNo
Into #FALLS
from
tableA as R
left join tableB as C
on R.ID = C.ID
where
R.[dateTime] between #sdate and #edate
/*Phys */
Select
DISTINCT
A.ID
,(A.ActualTime) as [DateTime]
,A.SeqID
into #Physio
from
tableC as A
left join #FALLS as Falls
on Falls.ID = A.ID
/* COMBINE RESULT */
Select
P1.ID
,P1.EmpNo
,P1.SeqID
from
(Select
DISTINCT
Falls.ID
,Falls.EmpNo
,MIN(Physio.[DateTime])
from
#FALLS as Falls
left join #Physio as Physio
on Falls.ID = Physio.ID
group by
Falls.ID
,Falls.EmpNo
) as P1
left join #Physio as P2
on P1.ID = P2.ID
How can i rewrite the sql without using temp tables.
I don't see the problem with using temp tables, but you can use a two CTEs instead:
DECLARE #sdate AS DATETIME
DECLARE #edate AS DATETIME
SET #sdate = '01-Apr-2016 00:00:00'
SET #edate = '31-Mar-2017 23:59:59'
;WITH Falls
AS (
SELECT DISTINCT R.ID
,C.EmpNo
FROM tableA AS R
LEFT JOIN tableB AS C ON R.ID = C.ID
WHERE R.[dateTime] BETWEEN #sdate
AND #edate
)
,Physio
AS (
SELECT DISTINCT A.ID
,(A.ActualTime) AS [DateTime]
,A.SeqID
FROM tableC AS A
LEFT JOIN Falls AS Falls ON Falls.ID = A.ID
)
SELECT P1.ID
,P1.EmpNo
,P1.SeqID
FROM (
SELECT DISTINCT Falls.ID
,Falls.EmpNo
,MIN(Physio.[DateTime])
FROM Falls AS Falls
LEFT JOIN Physio AS Physio ON Falls.ID = Physio.ID
GROUP BY Falls.ID
,Falls.EmpNo
) AS P1
LEFT JOIN Physio AS P2 ON P1.ID = P2.ID
the query below should bring the same result.
also this looks like a homework question.
declare #sdate as datetime
declare #edate as datetime
set #sdate = '01-Apr-2016 00:00:00'
set #edate = '31-Mar-2017 23:59:59'
Select DISTINCT
R.ID
,C.EmpNo
,MIN(Physio.ActualTime) SeqID
from
tableA as R
left join tableB as C
on R.ID = C.ID
left join tableC as Physio
on Falls.ID = Physio.ID
where
R.[dateTime] between #sdate and #edate
GROUP BY R.ID
,C.EmpNo