Need to speed up this SQL query - sql

My query has this structure:
SELECT DISTINCT (CO.CateringOrderId),
CO.CateringOrderNumber,
MC.FirstName + ' ' + MC.LastName AS "CustomerName",
CO.EventDate AS EventDate,
CO.IsCompleted,
CO.IsVerified,
MC.EmailId,
CAT.OfficePhone,
CAT.Mobile,
CAT.Fax,
CO.TotalInvoiceAmount,
CO.BarterCharityId,
(SELECT Sum (Amount)
FROM Catering_Order_Payment_Trans
WHERE CateringOrderId = CO.CateringOrderId) AS AmountReceived
FROM Catering_Orders CO,
Master_Customer MC,
Customer_Address_Trans CAT,
Catering_Order_Employee_Trans COET
WHERE MC.CompanyId = #p_CompanyId
AND (MC.CustomerId = #p_CustomerId OR #p_CustomerId = -1)
AND (CO.CateringOrderNumber LIKE '%' + #p_CateringOrderNumber + '%')
AND (CO.EventDate >= CONVERT (DATETIME, #p_FromDate) OR #p_FromDate = '')
AND (CO.EventDate <= CONVERT (DATETIME, #p_ToDate) OR #p_ToDate = '')
AND (CO.IsCompleted = #p_IsCompleted OR #p_IsCompleted = -1)
AND (COET.EmployeeId = #p_CatererId OR #p_CatererId = -1)
AND MC.CustomerId = CO.CustomerId
AND MC.PersonalAddressId = CAT.CustomerAddressId
AND (COET.CateringOrderId = CO.CateringOrderId
OR CO.CateringOrderId NOT IN
(SELECT CateringOrderId FROM Catering_Order_Employee_Trans))
AND (CAT.Mobile like '%' + #p_ContactNumber + '%' )
AND (CO.IsActive is null or CO.IsActive=1)
ORDER BY CO.CateringOrderId DESC
I think the SUM sub-query is slowing it. Please suggest me on how to speed it up.
Currently its execution time is around 7 - 10 seconds.

Try something like this -
SELECT DISTINCT
CO.CateringOrderId,
CO.CateringOrderNumber,
MC.FirstName + ' ' + MC.LastName AS CustomerName,
CO.EventDate AS EventDate,
CO.IsCompleted,
CO.IsVerified,
MC.EmailId,
CAT.OfficePhone,
CAT.Mobile,
CAT.Fax,
CO.TotalInvoiceAmount,
CO.BarterCharityId,
AmountReceived = (
SELECT SUM(t.Amount)
FROM dbo.Catering_Order_Payment_Trans t
WHERE t.CateringOrderId = CO.CateringOrderId
)
FROM (
SELECT *
FROM dbo.Catering_Orders
WHERE ISNULL(IsActive, 1) = 1
AND (IsCompleted = #p_IsCompleted OR #p_IsCompleted = -1)
AND CateringOrderNumber LIKE '%' + #p_CateringOrderNumber + '%'
AND EventDate BETWEEN
CONVERT(DATETIME, ISNULL(NULLIF(#p_FromDate, ''), '18000101'))
AND
CONVERT(DATETIME, ISNULL(NULLIF(#p_ToDate, ''), '30000101'))
) CO
JOIN dbo.Master_Customer MC ON MC.CustomerId = CO.CustomerId
JOIN dbo.Customer_Address_Trans CAT ON MC.PersonalAddressId = CAT.CustomerAddressId
LEFT JOIN (
SELECT *
FROM dbo.Catering_Order_Employee_Trans
WHERE EmployeeId = #p_CatererId
OR #p_CatererId = -1
) COET ON COET.CateringOrderId = CO.CateringOrderId
WHERE MC.CompanyId = #p_CompanyId
AND (MC.CustomerId = #p_CustomerId OR #p_CustomerId = -1)
AND CAT.Mobile LIKE '%' + #p_ContactNumber + '%'
The main problems in
AND (COET.CateringOrderId = CO.CateringOrderId
OR CO.CateringOrderId NOT IN
(SELECT CateringOrderId FROM Catering_Order_Employee_Trans))
and
(SELECT Sum (Amount)
FROM Catering_Order_Payment_Trans
WHERE CateringOrderId = CO.CateringOrderId) AS AmountReceived

Try:
SELECT CO.CateringOrderId,
CO.CateringOrderNumber,
MC.FirstName + ' ' + MC.LastName AS "CustomerName",
CO.EventDate AS EventDate,
CO.IsCompleted,
CO.IsVerified,
MC.EmailId,
CAT.OfficePhone,
CAT.Mobile,
CAT.Fax,
CO.TotalInvoiceAmount,
CO.BarterCharityId,
COPT.AmountReceived
FROM Catering_Orders CO
JOIN Master_Customer MC ON MC.CustomerId = CO.CustomerId
JOIN Customer_Address_Trans CAT ON MC.PersonalAddressId = CAT.CustomerAddressId
LEFT JOIN (SELECT CateringOrderId, Sum(Amount) AS AmountReceived
FROM Catering_Order_Payment_Trans
GROUP BY CateringOrderId) COPT
ON COPT.CateringOrderId = CO.CateringOrderId
WHERE MC.CompanyId = #p_CompanyId
AND (MC.CustomerId = #p_CustomerId OR #p_CustomerId = -1)
AND (CO.CateringOrderNumber LIKE '%' + #p_CateringOrderNumber + '%')
AND (CO.EventDate >= CONVERT (DATETIME, #p_FromDate) OR #p_FromDate = '')
AND (CO.EventDate <= CONVERT (DATETIME, #p_ToDate) OR #p_ToDate = '')
AND (CO.IsCompleted = #p_IsCompleted OR #p_IsCompleted = -1)
AND EXISTS
(SELECT NULL
FROM Catering_Order_Employee_Trans COET
WHERE COET.CateringOrderId = CO.CateringOrderId AND
(COET.EmployeeId = #p_CatererId OR #p_CatererId = -1) )
AND (CAT.Mobile like '%' + #p_ContactNumber + '%' )
AND (CO.IsActive is null or CO.IsActive=1)
ORDER BY CO.CateringOrderId DESC

To optimize your query you should edit the OR condition inserted inside AND conditions which really slow down your query
AND ( CO.EventDate <= CONVERT (DATETIME, #p_ToDate)
OR #p_ToDate = '')
should become something like
AND ( CO.EventDate <= CASE WHEN #p_ToDate = '' THEN
GETDATE()
ELSE
CONVERT (DATETIME,#p_ToDate)
END)
Also try to remove one by one the innested select both in select and in where to see which one most slows down the query

Related

Microsoft SQL Server: where logic - Column stored as an integer but represents a date in my table

I'm running into an issue with my Where clause;
AND CAST(h.chinto as DATETIME) >= DATEADD(DAY, -7, GetDate())
chinto is stored as an integer in the format YYYYMMDD and represents a date. Im trying to write a where clause to sort my results based on the last 30 days ect.
Ive tried try_convert to change the data type to a date but I cant seem to get it right. Always running into an the error: Arithmetic overflow error converting expression to data type datetime.
SELECT top 100
[ClaimNumber] = MAX(RIGHT('00000000' + convert(varchar(8),h.chclno),8) + RIGHT('00' + convert(varchar(8),h.chwkno),2)),
[EmployeeSSN] = RTRIM(MAX(RIGHT('000000000' + CONVERT(VARCHAR(9),m.edssno),9))),
[EmployeeID] = RTRIM(MAX(ee.edmemb)),
[EmployeeLastName] = RTRIM(MAX(m.edlnmk)),
[EmployeeFirstName] = RTRIM(MAX(m.edfnam)),
[PatientSSN] = RTRIM(MAX(RIGHT('000000000' + CONVERT(VARCHAR(9),e.eessno),9))),
[PatientDOB] = RTRIM(MAX(m.edbrdt)),
[PatientGender] = RTRIM(MAX(m.edsexx)),
-- m.edbrdt as 'PatientDOB',
--m.edsexx as 'PatientGender',
[FirstDateOfService] = MAX(left(convert(char(8),h.chinfr),4) + '-' + substring(convert(char(8),h.chinfr),5,2) + '-' + right(convert(char(8),h.chinfr),2) ),
[LastDateOfService] = MAX(left(convert(char(8),h.chinto),4) + '-' + substring(convert(char(8),h.chinto),5,2) + '-' + right(convert(char(8),h.chinto),2) ),
[ProviderName] = MAX(ps.pmname),
[ProviderAddress1] = MAX(CASE WHEN sn.npinpi = nps.NPI THEN RTRIM(nps.Prov_First_Line_Business_Practice_Location_Address) ELSE RTRIM(ps.pmadr1) COLLATE SQL_Latin1_General_Cp1_CS_AS END ),
[ProviderAddress2] = MAX(CASE WHEN sn.npinpi = nps.NPI THEN RTRIM(ISNULL(nps.Prov_Second_Line_Business_Practice_Location_Address,'')) ELSE RTRIM(ps.pmadr2) COLLATE SQL_Latin1_General_Cp1_CS_AS END ),
[ProviderCity] = MAX(CASE WHEN sn.npinpi = nps.NPI THEN RTRIM(ISNULL(nps.Prov_Business_Mailing_Address_City_Name,'')) ELSE RTRIM(ps.pmadr2) COLLATE SQL_Latin1_General_Cp1_CS_AS END ),
[ProviderState] = MAX(CASE WHEN sn.npinpi = nps.NPI THEN RTRIM(nps.Prov_Business_Practice_Location_Address_ST_Name) ELSE RTRIM(ps.pmstat) COLLATE SQL_Latin1_General_Cp1_CS_AS END ),
[ProviderZIP] = MAX(CASE WHEN sn.npinpi = nps.NPI THEN LEFT(nps.Prov_Business_Practice_Location_Address_Postal_CD,5) ELSE LEFT(ps.pmzpcd,5) COLLATE SQL_Latin1_General_Cp1_CS_AS END ),
--[ProviderTIN] ,
--[ProviderTINSuffix] ?,
[DiagnosisCode1] = RTRIM(MAX(h.chdgcd)),
[DiagnosisCode2] = RTRIM(MAX(ISNULL(h.chadgc_1,''))),
[DiagnosisCode3] = RTRIM(MAX(ISNULL(h.chadgc_2,''))),
[DiagnosisCode4] = RTRIM(MAX(ISNULL(h.chadgc_3,''))),
[DiagnosisCode5] = RTRIM(MAX(ISNULL(h.chadgc_4,''))),
[DiagnosisCode6] = RTRIM(MAX(ISNULL(h.chadgc_5,''))),
[DiagnosisCode7] = RTRIM(MAX(ISNULL(h.chadgc_6,''))),
[DiagnosisCode8] = RTRIM(MAX(ISNULL(h.chadgc_7,''))),
[DiagnosisCode9] = RTRIM(MAX(ISNULL(h.chadgc_8,''))),
--[ProcedureCode1?] = RTRIM(MAX(d.cdproc)) ---> clmdet missing prod code(s)/date(s) joined ACO.dbo.clmubf p
[ProcedureCode1] = RTRIM(MAX(ISNULL(p.cwprcd_1, ''))),
[ProcedureDate1] = RTRIM(MAX(ISNULL(p.cwprdt_1, ''))),
[ProcedureCode2] = RTRIM(MAX(ISNULL(p.cwprcd_2, ''))),
[ProcedureDate2] = RTRIM(MAX(ISNULL(p.cwprdt_2, ''))),
[ProcedureCode3] = RTRIM(MAX(ISNULL(p.cwprcd_3, ''))),
[ProcedureDate3] = RTRIM(MAX(ISNULL(p.cwprdt_3, ''))),
[ProcedureCode4] = RTRIM(MAX(ISNULL(p.cwprcd_4, ''))),
[ProcedureDate4] = RTRIM(MAX(ISNULL(p.cwprdt_4, ''))),
[ProcedureCode5] = RTRIM(MAX(ISNULL(p.cwprcd_5, ''))),
[ProcedureDate5] = RTRIM(MAX(ISNULL(p.cwprdt_5, ''))),
[ProcedureCode6] = RTRIM(MAX(ISNULL(p.cwprcd_6, ''))),
[ProcedureDate6] = RTRIM(MAX(ISNULL(p.cwprdt_6, ''))),
[TotalCharge] = SUM(d.cdtchg),
--[TotalCharge] = SUM(c.dichga?) --> drghis table missing from ACO.dbo, has all the info I need (clmdet d missing columns)
--[AllowableCharge] = ?,
[TotalIneligible] = SUM(d.cdinea),
--[TotalEligible] =,
[TotalDiscount] = SUM(d.cddisc),
[TotalDeductible] = SUM(d.cddeda),
[TotalCoPay] = SUM(d.cdcopa),
[TotalCoInsurance] = SUM(d.cdleva_1)
--[TotalPaid] = SUM(d.cdcoba?)
--[ClaimType]
FROM
ACO.dbo.clmhdr h
INNER JOIN ACO.dbo.clmdet d ON h.chclno = d.cdclno AND h.chwkno = d.cdwkno
INNER JOIN ACO.dbo.elgdep m ON h.chemno = m.ednmbr AND h.chdpcd = m.eddpcd
INNER JOIN ACO.dbo.elgemp e ON m.ednmbr = e.eenmbr
INNER JOIN ACO.dbo.elgdep ee ON e.eenmbr = ee.ednmbr AND ee.eddpcd = 'e'
INNER JOIN ACO.dbo.clmubf p ON h.chclno = p.cwclno
--INNER JOIN ACO.dbo.drghis? c ON h.chclno = c.diclno
LEFT OUTER JOIN ACO.dbo.prvmst pp ON d.cdpvno = pp.pmnmbr
LEFT OUTER JOIN ACO.dbo.prvmst ps ON d.cdspno = ps.pmnmbr
LEFT OUTER JOIN ACO.dbo.prvnpi sn ON d.cdspno = sn.npinmbr
LEFT OUTER JOIN ACO.dbo.prvnpi pn ON d.cdpvno = pn.npinmbr
LEFT OUTER JOIN [RIMSReport].[dbo].[NPI] nps ON sn.npinpi = nps.NPI
LEFT OUTER JOIN [RIMSReport].[dbo].[NPI] npp ON pn.npinpi = npp.NPI
WHERE
h.chgpno = 'CTT0001'
AND CAST(h.chinto as DATETIME) >= DATEADD(DAY, -7, GetDate())
GROUP BY
h.chclno, h.chinto
--m.edsexx, m.edbrdt
Casting int to date isn't allowed, but you can cast from string instead.
Try this: select cast(cast(h.chinto as varchar(10)) as date)

How to get column total for a table with two pivots

I have created a table joining two table having two pivots, Now I intend to get the total of all the column values for each row.
Below is my code which I am currently working on:
SELECT
*
FROM
(SELECT
time_tracker.date,
Users.FirstName + ' ' + Users.LastName AS username,
(CASE
WHEN ((datepart(hour, chk_in)) >= 12 OR
(datepart(hour, chk_out)) < 16)
THEN 0.5
ELSE 1
END) AS late,
TypeOfLeaves.leave_type, Userleavetyp.no_of_days
FROM
Users
INNER JOIN
time_tracker ON Users.ID = time_tracker.fk_userid
INNER JOIN
Userleavetyp ON Users.ID = Userleavetyp.fk_user
INNER JOIN
TypeOfLeaves ON Userleavetyp.fk_tol = TypeOfLeaves.ID
WHERE
(Users.FK_Status = 1)) AS P
For month days
PIVOT
(SUM(late) FOR date IN ("2018-01-01", "2018-01-02", "2018-01-03", "2018-01-04", "2018-01-05", "2018-01-06", "2018-01-07", "2018-01-08", "2018-01-09", "2018-01-10", "2018-01-11", "2018-01-12", "2018-01-13", "2018-01-14", "2018-01-15", "2018-01-16", "2018-01-17", "2018-01-18", "2018-01-19", "2018-01-20", "2018-01-21", "2018-01-22", "2018-01-23", "2018-01-24", "2018-01-25", "2018-01-26", "2018-01-27", "2018-01-28", "2018-01-29", "2018-01-30", "2018-01-31")
) AS pv1
For leave type
PIVOT
(SUM(no_of_days)
FOR leave_type IN ([Casual Leave], [Paid Leave], [Complimentary Leave])) AS pv2
I want the desired result to be something like this
enter image description here
Two things you can do:
Sum all pivoted columns: add an additional expression that sums all results. Change:
SELECT
*
FROM
--...
To:
SELECT
*,
Total = ISNULL([2018-01-01], 0)
+ ISNULL([2018-01-02], 0)
+ ISNULL([2018-01-03], 0)
+ ISNULL([2018-01-04], 0)
+ ISNULL([2018-01-05], 0)
+ ISNULL([2018-01-06], 0)
+ ISNULL([2018-01-07], 0)
+ ISNULL([2018-01-08], 0)
+ ISNULL([2018-01-09], 0)
+ ISNULL([2018-01-10], 0)
+ ISNULL([2018-01-11], 0)
+ ISNULL([2018-01-12], 0)
+ ISNULL([2018-01-13], 0)
+ ISNULL([2018-01-14], 0)
+ ISNULL([2018-01-15], 0)
+ ISNULL([2018-01-16], 0)
+ ISNULL([2018-01-17], 0)
+ ISNULL([2018-01-18], 0)
+ ISNULL([2018-01-19], 0)
+ ISNULL([2018-01-20], 0)
+ ISNULL([2018-01-21], 0)
+ ISNULL([2018-01-22], 0)
+ ISNULL([2018-01-23], 0)
+ ISNULL([2018-01-24], 0)
+ ISNULL([2018-01-25], 0)
+ ISNULL([2018-01-26], 0)
+ ISNULL([2018-01-27], 0)
+ ISNULL([2018-01-28], 0)
+ ISNULL([2018-01-29], 0)
+ ISNULL([2018-01-30], 0)
+ ISNULL([2018-01-31], 0)
FROM
--...
Calculate the total on another subquery and join at the end to retrieve the total:
;WITH ToPivot AS
(
SELECT
time_tracker.date,
Users.FirstName + ' ' + Users.LastName AS username,
(CASE
WHEN ((datepart(hour, chk_in)) >= 12 OR
(datepart(hour, chk_out)) < 16)
THEN 0.5
ELSE 1
END) AS late,
TypeOfLeaves.leave_type,
Userleavetyp.no_of_days
FROM
Users
INNER JOIN
time_tracker ON Users.ID = time_tracker.fk_userid
INNER JOIN
Userleavetyp ON Users.ID = Userleavetyp.fk_user
INNER JOIN
TypeOfLeaves ON Userleavetyp.fk_tol = TypeOfLeaves.ID
WHERE
(Users.FK_Status = 1)
),
LateTotals AS
(
SELECT
T.username,
Total = SUM(late)
FROM
ToPivot AS T
WHERE
T.date IN ('2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04', '2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08', '2018-01-09', '2018-01-10', '2018-01-11', '2018-01-12', '2018-01-13', '2018-01-14', '2018-01-15', '2018-01-16', '2018-01-17', '2018-01-18', '2018-01-19', '2018-01-20', '2018-01-21', '2018-01-22', '2018-01-23', '2018-01-24', '2018-01-25', '2018-01-26', '2018-01-27', '2018-01-28', '2018-01-29', '2018-01-30', '2018-01-31')
GROUP BY
T.username
)
SELECT
PV2.*,
L.Total
FROM
ToPivot AS P
PIVOT
(SUM(late) FOR date IN ("2018-01-01", "2018-01-02", "2018-01-03", "2018-01-04", "2018-01-05", "2018-01-06", "2018-01-07", "2018-01-08", "2018-01-09", "2018-01-10", "2018-01-11", "2018-01-12", "2018-01-13", "2018-01-14", "2018-01-15", "2018-01-16", "2018-01-17", "2018-01-18", "2018-01-19", "2018-01-20", "2018-01-21", "2018-01-22", "2018-01-23", "2018-01-24", "2018-01-25", "2018-01-26", "2018-01-27", "2018-01-28", "2018-01-29", "2018-01-30", "2018-01-31")
) AS pv1
PIVOT
(SUM(no_of_days)
FOR leave_type IN ([Casual Leave], [Paid Leave], [Complimentary Leave])
) AS pv2
LEFT JOIN LateTotals AS L ON L.username = pv2.username

Optimizing SQL query, altering ORs

With below condition query executes very long time. I think it depends from or conditions. How I can alternate these ors?
WHERE (p.tran_number = LTRIM(RTRIM(#tran_number)) OR ISNULL(LTRIM(RTRIM(#tran_number)), '') = '')
AND (CAST(p.fiscal_date AS DATE) >= CAST(#begin_date AS DATE) OR #begin_date IS NULL)
AND (CAST(p.fiscal_date AS DATE) <= CAST(#end_date AS DATE) OR #end_date IS NULL)
AND CAST(#end_date AS DATE)
AND (p.operation_type = #operation_type OR #operation_type = '-1')
AND (
ce.username = #username
OR #role_code LIKE '%admin%'
OR #role_code LIKE '%Statists_GO%'
OR (
(ce.username IN (
SELECT e.domain_username
FROM #childTable c
LEFT JOIN FstP.dbo.employees e ON e.id = c.obj_id
AND c.obj_type = 'employee'
)
)
AND #role_code LIKE '%supervisor%')
)
AND (p.rnm = #rnm OR ISNULL(#rnm, '') = '')
AND (ce.username = #author OR ISNULL(#author, '') = '')
AND (
d2.docs_num = #policy_number
OR dGate.DealNumber = #policy_number
OR ISNULL(#policy_number, '') = ''
)
ORDER BY insert_date DESC, fiscal_date DESC
SET #begin_date = CAST(#begin_date AS DATE)
SET #end_date = DATEADD(DAY, 1, CAST(#end_date AS DATE))
SET #tran_number = LTRIM(RTRIM(#tran_number))
...
WHERE (p.tran_number = #tran_number OR ISNULL(#tran_number, '') = '')
AND (p.fiscal_date >= #begin_date OR #begin_date IS NULL)
AND (p.fiscal_date < #end_date OR #end_date IS NULL)
AND (p.operation_type = #operation_type OR #operation_type = '-1')
AND (
ce.username = #username
OR #role_code LIKE '%admin%'
OR #role_code LIKE '%Statists_GO%'
OR (
ce.username IN (
SELECT e.domain_username
FROM #childTable c
JOIN FstP.dbo.employees e ON e.id = c.obj_id
AND c.obj_type = 'employee'
)
AND #role_code LIKE '%supervisor%'
)
)
AND (p.rnm = #rnm OR ISNULL(#rnm, '') = '')
AND (ce.username = #author OR ISNULL(#author, '') = '')
AND (
d2.docs_num = #policy_number
OR dGate.DealNumber = #policy_number
OR ISNULL(#policy_number, '') = ''
)
ORDER BY insert_date DESC, fiscal_date DESC
OPTION(RECOMPILE)

Concatenating row values using Inner Join

I have this query that I'm using to join two tables for an update statement. This is the query that I built:
DECLARE #DocHoldReasons VARCHAR(8000)
SET #DocHoldReasons = 'DocType Hold'
UPDATE dbo.EpnPackages
SET Error = 1, Msg = COALESCE (#DocHoldReasons + ': ', '') + cv.Value
FROM EpnPackages p
INNER JOIN EpnCountyValues cv ON cv.CountyId = p.CountyId and cv.ValueName = 'DocHoldReason'
WHERE p.Status = 1000
AND p.Error = 0
There are two rows in the EpnCountyValues table with the same ValueName, and I need them both concatenated, and I'm having a tough time doing it. All I can get is the first row value. This is what my resulting string should look like - 'DocType Hold: Test: Test.124.'
eidt: I need the rows with the same ValueName to be concatenated for the update query. There could be more than two rows with ValueName = DocHoldReason
Here's the structure of the EpnCountyValues table:
CountyValueId CountyId ValueName Value
1 1 DocHoldReason Test
2 2 xyz Test1
3 3 DocHoldReason Test.124.
Any help would be greatly appreciated. Thanks!
You can do what you want by pre-aggregating the table before the join. If there are only two values and you don't care about the order, then this will work:
DECLARE #DocHoldReasons VARCHAR(8000);
SET #DocHoldReasons = 'DocType Hold';
UPDATE dbo.EpnPackages
SET Error = 1,
Msg = (COALESCE(#DocHoldReasons + ': ', '') + minv +
(case when minv <> maxv then ': ' + maxv else '' end)
)
FROM EpnPackages p INNER JOIN
(select cv.CountyId, min(cv.value) as minv, max(cv.value) as maxv
from EpnCountyValues cv
where cv.ValueName = 'DocHoldReason'
) cv
ON cv.CountyId = p.CountyId
WHERE p.Status = 1000 AND p.Error = 0;
EDIT:
For more than two values, you have to do string concatenation. That is "unpleasant" in SQL Server. Here is the approach:
DECLARE #DocHoldReasons VARCHAR(8000);
SET #DocHoldReasons = 'DocType Hold';
UPDATE dbo.EpnPackages
SET Error = 1,
Msg = (COALESCE(#DocHoldReasons + ': ', '') +
stuff((select ': ' + cv.value
from EpnCountyValues cv
where cv.ValueName = 'DocHoldReason' and
cv.CountyId = p.CountyId
for xml path ('')
), 1, 2, '')
)
WHERE p.Status = 1000 AND p.Error = 0;
This version does it using a correlated subquery rather than a join with an aggregation.
EDIT II:
You can fix this with an additional coalesce:
DECLARE #DocHoldReasons VARCHAR(8000);
SET #DocHoldReasons = 'DocType Hold';
UPDATE dbo.EpnPackages
SET Error = 1,
Msg = (COALESCE(#DocHoldReasons + ': ', '') +
COALESCE(stuff((select ': ' + cv.value
from EpnCountyValues cv
where cv.ValueName = 'DocHoldReason' and
cv.CountyId = p.CountyId
for xml path ('')
), 1, 2, ''), '')
)
WHERE p.Status = 1000 AND p.Error = 0;
You can join the EpnCountyValues table twice!
Something like this,
DECLARE #DocHoldReasons VARCHAR(8000)
SET #DocHoldReasons = 'DocType Hold'
Select #DocHoldReasons + ': ' + ev1.Value + ': ' + ev2.Value
From EpnPackages p
Join EpnCountyValues ev1 on p.packageID = ev1.packageID
Join EpnCountyValues ev2 on ev1.ValueName = ev2.ValueName
Where ev1.ValueName = 'DocHoldRegion'
And p.status = 1000
And p.error = 0
Does that select look right to you? If so, run the update. I always try to run a select before an update. I have to admit, I'm a bit confused why you're joining on CountyID, but then it seems like you'll be updating the values from different counties?

How to Avoid dynamic sql

Can I get some help, I am trying to avoid dynamic sql, the dynamic sql works but its there any other way to build this without dynamic sql, I am trying a lot of stuff but getting errors, your help will be appreciated.
declare #strSQL varchar(8000)
set #strSQL = 'Select
ParentFName, ParentLName, ParentMiddleName,
MailingAddressLine1, MailingAddressLine2, City, State, ZipCode,
PS.SchoolID, PS.SchoolName, FirstName, LastName, MiddleName,
CONVERT(varchar(12), SE.Birthday, 101) AS [Birthday],
SE.GTID, SystemID,Grade, Report_Type, Race, Sex, NON_Funded_Flag,
DATEDIFF(YY,Birthday , getdate()) -
CASE
WHEN(
(MONTH(BirthDay)*100 + DAY(BirthDay)) >
(MONTH(getdate())*100 + DAY(getdate()))
) THEN 1
ELSE 0 END AS Age,
KG, GR01_03, GR04_05, GR06_08_Middle_Grade, GR06_08_middle_school,
GR09_12, EIP_KG, EIP_01_03,EIP_04_05,LEVEL_1,LEVEL_2,LEVEL_3,LEVEL_4,LEVEL_5,GIFTED, REMEDIAL,VOCATIONAL_HS_LAB, SED, --STUDY_HALL,
NON_FUNDED, --POST_SECOND_OPTION,
ESOL_ITINERANT, ESOL_NON_ITINERANT, TOTAL_ESOL_SEGMENTS,
FiscalYear, TOTAL_FTE_SEGMENTS, AnnualTuition,
CONVERT(varchar(12), SE.EnrollmentDate,101) AS [Enrollment Date],
CONVERT(varchar(12), SE.WithdrawalDate,101) AS [Withdrawal Date],
WD.LookupValueDescription as WithdrawalReason,
FREE_REDUCED_LUNCH, PRIMARY_AREA, GNET_FLAG,
EstAwardAmount--, previous_year
From
StudentEnrollment SE
inner join (
select * from openquery([FINANCE], ''select * from scholarship.sp_eligible_students Where Fiscal_Year = ''''' + convert(varchar, #FiscalYear) + ''''' '') ) ES ON
SE.GTID = ES.GTID Inner Join
(select FP.FiscalYear, PrivateSchool.* from PrivateSchool
INNER JOIN FiscalYearPrivateSchool FP ON PrivateSchool.PrivateSchoolID = FP.PrivateSchoolID AND FP.FiscalYear = ' + #FiscalYear + ') PS
ON SE.PrivateSchoolID = PS.PrivateSchoolID AND ES.Fiscal_Year = PS.FiscalYear Left outer Join
vLookUps WD ON SE.WithdrawalreasonId = WD.LookUpID
WHERE SE.isActive = 1 AND PS.isactive = 1
AND (' + #SchoolID + ' = -1 or SchoolID = ' + #SchoolID + ' )
AND (' + #FiscalYear + ' = -1 OR FiscalYear = ' + #FiscalYear + ')
ORDER BY SchoolName, LastName, Firstname, GTID'
--print (#strSQL)
exec (#strSQL)
END
SET NOCOUNT ON
declare #oq varchar(200)
set #og = 'select * from scholarship.sp_eligible_students Where Fiscal_Year ='+ convert(varchar, #FiscalYear)
select * into #a from openquery([FINANCE], #oq)
Select
ParentFName, ParentLName, ParentMiddleName,
MailingAddressLine1, MailingAddressLine2, City, State, ZipCode,
PS.SchoolID, PS.SchoolName, FirstName, LastName, MiddleName,
CONVERT(varchar(12), SE.Birthday, 101) AS [Birthday],
SE.GTID, SystemID,Grade, Report_Type, Race, Sex, NON_Funded_Flag,
DATEDIFF(YY,Birthday , getdate()) -
CASE
WHEN(
(MONTH(BirthDay)*100 + DAY(BirthDay)) >
(MONTH(getdate())*100 + DAY(getdate()))
) THEN 1
ELSE 0 END AS Age,
KG, GR01_03, GR04_05, GR06_08_Middle_Grade, GR06_08_middle_school,
GR09_12, EIP_KG, EIP_01_03,EIP_04_05,LEVEL_1,LEVEL_2,LEVEL_3,LEVEL_4,LEVEL_5,GIFTED, REMEDIAL,VOCATIONAL_HS_LAB, SED,
NON_FUNDED,
ESOL_ITINERANT, ESOL_NON_ITINERANT, TOTAL_ESOL_SEGMENTS,
FiscalYear, TOTAL_FTE_SEGMENTS, AnnualTuition,
CONVERT(varchar(12), SE.EnrollmentDate,101) AS [Enrollment Date],
CONVERT(varchar(12), SE.WithdrawalDate,101) AS [Withdrawal Date],
WD.LookupValueDescription as WithdrawalReason,
FREE_REDUCED_LUNCH, PRIMARY_AREA, GNET_FLAG,
EstAwardAmount
From
StudentEnrollment SE
inner join #a ES ON
SE.GTID = ES.GTID Inner Join
(select FP.FiscalYear, PrivateSchool.* from PrivateSchool
INNER JOIN FiscalYearPrivateSchool FP ON PrivateSchool.PrivateSchoolID = FP.PrivateSchoolID AND FP.FiscalYear = #FiscalYear) PS
ON SE.PrivateSchoolID = PS.PrivateSchoolID AND ES.Fiscal_Year = PS.FiscalYear Left outer Join
vLookUps WD ON SE.WithdrawalreasonId = WD.LookUpID
WHERE SE.isActive = 1 AND PS.isactive = 1
AND (#SchoolID = -1 or SchoolID = #SchoolID )
AND (#FiscalYear = -1 OR FiscalYear = #FiscalYear)
ORDER BY SchoolName, LastName, Firstname, GTID
drop table #a
If and when this fails. Try fixing it.