Return SQL Sub Query with a variable inside Select - sql

My Application is a cash register. The following query takes a TransactionID and returns one or more rows of items sold in this single transaction i.e. for TransactionID = 28715:
DECLARE #SalesItems varchar(250);
DECLARE #TransactionID int;
SET #TransactionID = 28715;
Select #SalesItems = coalesce(#SalesItems + ', ', '') + CAST(TransactionsPosLines.Description as varchar(250))
From
TransactionsPosLines
where TransactionsPosLines.TransactionId = #TransactionID
select #SalesItems
and returns:
"Widget A, Widget B, Widget C" as a single string.
I also have an end of day transaction report which I want to append the string (Widget A etc...) onto the end of the transaction report.
Select
Transactions.TransactionId,
Transactions.TransactionDate,
Transactions.MoneyIn,
Transactions.MoneyOut,
Transactions.Description,
PaymentMethods.PaymentMethodName,
Transactions.TransactionRef,
Membership.Username,
Tills.Description As 'Till Name',
Transactions.Reason,
-- FOR THIS LAST COLUMN HERE I WANT TO SHOW THE OUTPUT OF THE QUERY ABOVE
====> SalesItems
From
Transactions Left Outer Join
Tills
On Transactions.TillId = Tills.TillId Inner Join
PaymentMethods
On Transactions.PaymentMethodId = PaymentMethods.PaymentMethodsID Inner Join
Membership
On Transactions.UserId = Membership.UserId Inner Join
Where
Transactions.TransactionDate >= #DateStart And
Transactions.TransactionDate <= #DateEnd
So when I run this report I get something like this:
TransactionId TransactionDate MoneyIn MoneyOut Description PaymentMethodName TransactionRef Username Till Name Reason SalesItems
28715 31/08/2016 09:07 119.99 0 Sale - Card Card 24881 Chantal Till1 Null Widget A, Widget B, Widget C

CROSS APPLY WITH FOR XML CONCATENATION METHOD:
Select
t.TransactionId,
t.TransactionDate,
t.MoneyIn,
t.MoneyOut,
t.Description,
p.PaymentMethodName,
t.TransactionRef,
m.Username,
tl.Description As 'Till Name',
t.Reason,
c.SalesItems
From
Transactions t
LEFT JOIN Tills tl
ON t.TillId = tl.TillId
INNER JOIN PaymentMethods p
ON t.PaymentMethodId = p.PaymentMethodID
INNER JOIN Membership m
On t.UserId = m.UserId
CROSS APPLY
(SELECT STUFF(
(SELECT ',' + CAST(tp.Description AS VARCHAR(100))
FROM
TransactionPostLines tp
WHERE t.TransactionId = tp.TransactionId
FOR XML PATH(''))
,1,1,'') as SalesItems) c
Where
t.TransactionDate >= #DateStart
AND t.TransactionDate <= #DateEnd
AS Sub Select in column Definition:
Select
t.TransactionId,
t.TransactionDate,
t.MoneyIn,
t.MoneyOut,
t.Description,
p.PaymentMethodName,
t.TransactionRef,
m.Username,
tl.Description As 'Till Name',
t.Reason,
STUFF(
(SELECT ',' + CAST(tp.Description AS VARCHAR(100))
FROM
TransactionPostLines tp
WHERE t.TransactionId = tp.TransactionId
FOR XML PATH(''))
,1,1,'') as SalesItems
From
Transactions t
LEFT JOIN Tills tl
ON t.TillId = tl.TillId
INNER JOIN PaymentMethods p
ON t.PaymentMethodId = p.PaymentMethodID
INNER JOIN Membership m
On t.UserId = m.UserId
Where
t.TransactionDate >= #DateStart
AND t.TransactionDate <= #DateEnd
Note using table aliases makes the code easier to read and to write!

I have used cross apply in order to apply result to inner query to each row of your main query. Check whether this helps you:
Select
Transactions.TransactionId,
Transactions.TransactionDate,
Transactions.MoneyIn,
Transactions.MoneyOut,
Transactions.Description,
PaymentMethods.PaymentMethodName,
Transactions.TransactionRef,
Membership.Username,
Tills.Description As 'Till Name',
Transactions.Reason,
-- HERE >>
--SalesItems =
dt.salesItems
From
Transactions Left Outer Join
Tills
On Transactions.TillId = Tills.TillId Inner Join
PaymentMethods
On Transactions.PaymentMethodId = PaymentMethods.PaymentMethodsID Inner Join
Membership
On Transactions.UserId = Membership.UserId
cross apply (
select distinct stuff((
Select ',' + CAST(TransactionsPosLines.Description as varchar(250))
From
TransactionsPosLines
where TransactionsPosLines.TransactionId = Transactions.TransactionId
FOR XML PATH('')),1,1,'') as salesItems
) as dt
-- TransactionsPosLines
-- On TransactionsPosLines.TransactionId = Transactions.TransactionId
Where
Transactions.TransactionDate >= #DateStart And
Transactions.TransactionDate <= #DateEnd

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.

Query is working fine in second execution but taking too much time in first execution

I am writing a query which is accepting a comma separated string and calculating the sum of transaction. which is working fine as result wise but taking too much time to execute in first attempt. I understand its need tuning but didn't find out the exact reason can any one point me whats wrong with my query.
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) [Amount], convert(char(10),FT.TranDate,126) [Date]
from FeeTransaction FT
Inner Join (
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
) PA ON FT.Id = PA.TranMainId
Inner Join Patient_Account XP ON PA.Id = XP.Id
Inner Join Master_Fee MF ON XP.FeeId = MF.Id
INNER Join Master_Patient MP ON FT.PID = MP.Id
Inner Join Master_FeeType TY ON MF.FeeTypeId = TY.Id
Left JOIN FeeTransaction CT on FT.TransactionId = CT.TransactionId AND CT.TranDate between '2019'+'08'+'01' and '2019'+'08'+'31' and CT.[Status] <> 'A' AND isnull(CT.IsCancel,0) = 1
Where convert(nvarchar,FT.TranDate,112) between '2019'+'08'+'01' and '2019'+'08'+'31' AND FT.[Status] = 'A' AND XP.FeeId in (SELECT val FROM dbo.f_split(#IDs, ','))
AND isnull(FT.IsCancel,0) = 0 AND FT.EntryBy = 'rajan'
Group By convert(char(10),FT.TranDate,126)
I would rephrase the query a bit:
select coalesce(SUM(FT.PaidAmt), 0) - coalesce(SUM(CT.PaidAmt), 0)as [Amount],
convert(char(10),FT.TranDate,126) [Date]
from FeeTransaction FT join
(select xp.*,
coalesce(sum(p.amttopay) over (TranMainId), 0) as amt
from Patient_Account XP ON PA.Id = XP.Id
) xp join
Master_Fee MF
on XP.FeeId = MF.Id join
Master_Patient MP
on FT.PID = MP.Id join
Master_FeeType TY
on MF.FeeTypeId = TY.Id left join
FeeTransaction CT
on FT.TransactionId = CT.TransactionId and
CT.TranDate between '20190801' and '20190831' and
CT.[Status] <> 'A' and
CT.IsCanel = 1
where FT.TranDate >= '20190801' and and
FT.TranDate < '20190901'
FT.[Status] = 'A' AND
XP.FeeId in (SELECT val FROM dbo.f_split(#IDs, ',')) and
(FT.IsCancel = 0 or FT.IsCancel IS NULL) and
FT.EntryBy = 'rajan'
Group By convert(char(10), FT.TranDate, 126)
Then for this version, you specifically an index on FeeTransaction(EntryBy, Status, TranDate, Cancel).
Note the following changes:
You do not need to aggregate Patient_Account as a subquery. Window functions are quite convenient.
Your date comparisons preclude the use of indexes. Converting dates to strings is a bad practice in general.
You have over-used isnull().
I assume that the appropriate indexes are in place for the joins.
I would use STRING_SPLIT and Common Table Expressions and do away with date conversions:
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
;WITH CTE_ID AS
(
SELECT value AS ID FROM STRING_SPLIT(#IDs, ',');)
),
MaxPatient
AS
(
SELECT MAX(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
)
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) As [Amount],
convert(char(10),FT.TranDate,126) [Date]
FROM FeeTransaction FT
INNER JOIN MaxPatient PA
ON FT.Id = PA.TranMainId
INNER JOIN Patient_Account XP
ON PA.Id = XP.Id
INNER JOIN Master_Fee MF
ON XP.FeeId = MF.Id
INNER Join Master_Patient MP
ON FT.PID = MP.Id
INNER JOIN Master_FeeType TY
ON MF.FeeTypeId = TY.Id
INNER JOIN CTE_ID
ON XP.FeeId = CTE_ID.ID
LEFT JOIN FeeTransaction CT
ON FT.TransactionId = CT.TransactionId AND
CT.TranDate >= '20190801' AND CT.TranDate < '20190831' AND
CT.[Status] <> 'A' AND isnull(CT.IsCancel,0) = 1
WHERE FT.TranDate >= '20190801' and FT.TranDate < '20190831' AND
FT.[Status] = 'A' AND
ISNULL(FT.IsCancel,0) = 0 AND
FT.EntryBy = 'rajan'
GROUP BY CAST(FT.TranDate AS Date)
Not only is your query slow, but it appear that it is giving incorrect output.
i) When you are not using any column of Patient_Account in your resultset then why are you writing this sub query?
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
ii) Avoid using <>.So Status must be either 'A' or 'I'
so write this instead CT.[Status] = 'I'
iii) What is the correct data type of TranDate ?Don't use function in where condition. .
iv) No need of isnull(CT.IsCancel,0) = 1,instead write CT.IsCancel = 1
So my script is just outline, but it is easy to understand.
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
create table #temp(id int)
insert into #temp(id)
SELECT val FROM dbo.f_split(#IDs, ',')
declare #FromDate Datetime='2019-08-01'
declare #toDate Datetime='2019-08-31'
-- mention all column of FeeTransaction that you need in this query along with correct data type
-- Store TranDate in this manner convert(char(10),FT.TranDate,126) in this table
create table #Transaction()
select * from FeeTransaction FT
where FT.TranDate>=#FromDate and FT.TranDate<#toDate
and exists(select 1 from #temp t where t .val=ft.id)
-- mention all column of Patient_Account that you need in this query along with correct data type
create table #Patient_Account()
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
where exists(select 1 from #Transaction T where t.id=PA.TranMainId)
Group By P.TranMainId
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) [Amount], TranDate [Date]
from #Transaction FT
Inner Join #Patient_Account XP ON PA.Id = XP.Id
Inner Join Master_Fee MF ON XP.FeeId = MF.Id
INNER Join Master_Patient MP ON FT.PID = MP.Id
Inner Join Master_FeeType TY ON MF.FeeTypeId = TY.Id
Left JOIN #Transaction CT on FT.TransactionId = CT.TransactionId AND CT.[Status] = 'I' AND CT.IsCancel = 1
Where AND FT.[Status] = 'A' AND XP.FeeId in (SELECT val FROM #temp t)
AND FT.IsCancel = 0 AND FT.EntryBy = 'rajan'
Group By TranDate

In-memory table multiple INNER JOIN

I am trying to update a report in SSRS. The query is build by another colleague using a stored procedure, whom has left the project and can't contact anymore.
He used an in-memory table for all batches in order to add some aggregations.
The columns as outputs are:
BatchID
TransformDate
SourceSystem
CompanyType
MAX(B.FooterLines) AS FooterTotalLines
MAX(SRC.TotalLines) AS SourceTotalLines
MAX(BalancingLinesTable.BalancingLines) AS BalancingLines
SUM(STG.TotalLines) AS StagingTotalLines
(CAST(STG.Company AS int) * 1000000) + B.BatchID AS CompanyCode
However I need to add an extra column called Balancing lines. I developed the query for it and it works:
SELECT COUNT(0) as "Balancing lines"
FROM [Source].[Staging].[TransactionLine] T
INNER JOIN
[Source].[Staging].HeaderLine H
ON T.HeaderID = H.HeaderID
where H.BatchID = 1234* and H.SourceSystemInstance = 'ABC' and AccountNumber = '98765'
*1234 should be variable -> B.BatchID and also the SourseSystemInstance 'ABC'-> B.SourceSystem
But, the stored procedure written by my collegue is still foreign to me. Do you know how to 'add' my working query to his working stored procedure?
For clarity the table used:
#batches B
HeaderLine H
FooterLine FL
'INNER JOIN table' BalancingLinesTable
'INNER JOIN table' SRC
'LEFT JOIN table' STG
The stored procedure:
USE [Source]
ALTER PROCEDURE [dbo].[usp_GetSomeCounts] (
#StartAt datetime
)
AS BEGIN
SET NOCOUNT ON;
-- Set a default for start date if none is specified
SELECT #StartAt = ISNULL(#StartAt, DATEADD(dd, -7, GETDATE()))
-- Use an in-memory table for all batches for the specified period
DECLARE #batches TABLE(BatchID int, TransformDate datetime, HeaderID nvarchar(36), CompanyType nvarchar(30), SourceSystem nvarchar(4), FooterLines int)
-- Fill in-memory table batches
INSERT INTO #batches (
BatchID
,TransformDate
,HeaderID
,CompanyType
,SourceSystem
,FooterLines
)
SELECT
H.BatchID
,H.TransformDate
,H.HeaderID
,CompanyTypeID
,H.SourceSystemInstance
,ISNULL(FL.TotalTransactionLines, 0)
FROM
Staging.HeaderLine H WITH (NOLOCK)
INNER JOIN
Staging.FooterLine FL WITH (NOLOCK)
ON
H.HeaderID = FL.HeaderID
WHERE
H.BatchDate >= #StartAt
ORDER BY
H.BatchID
/* Using in-memory table 'batches', count all valid transactions in both Source and Staging
databases. Include the footer totals */
SELECT
B.BatchID
, B.TransformDate
, B.SourceSystem
, B.CompanyType
, MAX(B.FooterLines) AS FooterTotalLines
, MAX(SRC.TotalLines) AS SourceTotalLines
, MAX(BalancingLinesTable.BalancingLines) AS BalancingLines
, SUM(STG.TotalLines) AS StagingTotalLines
, (CAST(STG.Company AS int) * 1000000) + B.BatchID AS CompanyCode
FROM
#batches B
INNER JOIN (
SELECT
B.BatchID
,B.HeaderID
,COUNT(0) as BalancingLines
FROM
#batches B
-- this 'inner join table' BalancingLinesTable is what I added
INNER JOIN
Staging.TransactionLine T WITH (NOLOCK)
ON B.HeaderID = T.HeaderID
INNER JOIN
Staging.HeaderLine H WITH (NOLOCK)
ON T.HeaderID = H.HeaderID
WHERE H.BatchID = B.BatchID AND H.SourceSystemInstance = B.SourceSystem AND AccountNumber = 399990
GROUP BY
B.BatchID
,B.HeaderID
) BalancingLinesTable ON B.BatchID = BalancingLinesTable.BatchID
INNER JOIN (
SELECT
B.BatchID
,B.HeaderID
,COUNT(0) AS TotalLines
FROM
#batches B
INNER JOIN
Staging.TransactionLine T WITH (NOLOCK)
ON
B.HeaderID = T.HeaderID
WHERE
T.LineStatus = 'N'
GROUP BY
B.BatchID
,B.HeaderID ) SRC ON B.BatchID = SRC.BatchID
LEFT JOIN (
SELECT
B.BatchID
,B.HeaderID
,MT.Company
,COUNT(0) AS TotalLines
FROM
#batches B
INNER JOIN
[Production].[dbo].[Mutated_Transactions] MT WITH (NOLOCK)
ON
B.HeaderID = MT.HeaderID
WHERE
MT.RowHasError = 'N'
GROUP BY
B.BatchID
,B.HeaderID
,MT.Company) STG ON SRC.BatchID = STG.BatchID AND SRC.HeaderID = STG.HeaderID
GROUP BY
B.BatchID
,B.TransformDate
,B.SourceSystem
,B.CompanyType
,STG.Company
ORDER BY
B.TransformDate desc
,B.BatchID
END
Wow.. after changing accoutnumber = 98765 to '98765' I got rid of the error. But the resulting output is still empty. It appears I forgot to add the [BalancingLines] in the SSRS column. Yeah.. I know..

Single Line separated records in SQL SERVER Query result

I had a query that returned multiple rows from a table. Then I converted that query to this one:
;with mycte as
(select s.FirstName + ' ' + s.LastName as Name from ClientStaff cs
left outer join Staff s on s.Id = cs.StaffId
left outer join GeneralStatus gs on gs.Id = s.StatusId
where cs.ClientId = #clientId and gs.Name = 'Active')
select #staff = (select distinct staff = REPLACE(REPLACE(REPLACE((select Name AS [data()] FROM mycte a
order by a.Name for xml path),'</row><row>',', '),'</row>',''),'<row>','') from mycte b)
It returns those rows in a single comma-separated row.
Now I don't want comma-separated values, instead I want single-line-separated values.
Can anyone tell me if it is possible or not?
Thanks in advance.
declare #staff varchar(max)
;with mycte as
(
select distinct s.FirstName + ' ' + s.LastName as Name
from ClientStaff cs
left outer join Staff s on
s.Id = cs.StaffId
left outer join GeneralStatus gs on
gs.Id = s.StatusId
where cs.ClientId = #clientId and gs.Name = 'Active'
)
select #staff = isnull(#staff + char(13), '') + Name
from mycte b
print #staff

How can I use Sql to Order By This Statement?

How can I order the list 'widgets_spec by number of widgets?
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,widgets) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and widgets is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as widgets_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Right now output looks like:
<li>10<br> <li>12<br> <li>15<br> <li>8<br>
When I want it to look like:
<li>8<br> <li>10<br> <li>12<br> <li>15<br>
Thanks for your help.
EDIT: I'm trying to order the internal select statement that concatenates the values.
You do not need both Distinct and Group By. You should use one or the other. In this case, I believe you have to use Group By for it to work.
Select m.p_c_id
, (
Select '<li>' + Cast( m2.num_of_lights As varchar(10)) + '<br /> '
From dbo.spec_master As m2
Where m.p_c_id = m2.p_c_id
And m2.num_of_lights Is Not Null
Group By m2.num_of_lights
Order By m2.num_of_lights
For Xml Path(''), type).value('.[1]', 'nvarchar(max)'
) As numLights_spec
From dbo.spec_master As m
Inner Join dbo.ProductVaration As pv
On pv.p_c_id = m.p_c_id
Inner Join dbo.Varation As v
On v.varation_id = pv.varation_type_id
Where v.varation_id = 4
Group by m.p_c_id
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
ORDER BY convert(varchar,num_of_lights)
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
) As SubA
Some of the other answers here won't work, since ordering by the now-varchar num_of_lights will put '8' after '15' as is happening now. You want to order the numLights numerically, which isn't going to happen with those html tags around them. You can add a subselect to your subselect so that you order them, then select them with the tags around them. Example (not tested):
SELECT * FROM (
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from (select distinct p_c_id, num_of_lights from dbo.spec_master order by num_of_lights) m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Personally, I'd just add the html tags in whatever back-end code is getting the result of the query.