How to use alias in where clause in SQL Server - sql-server

I have following query and i am getting perfect result what i want but i want to use stManufacturerPartReference alias in where clause condition Like following second query but it gives me error.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted <> 1
AND flgIsHistoricItem <> 1 AND (product.inCompanyId = 1) )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;
i want to use stManufacturerPartReference in Where Clause Like Following.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted <> 1
AND flgIsHistoricItem <> 1 AND (product.inCompanyId = 1) AND stManufacturerPartReference LIKE '%ABC DEF%' )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;
But it Gives me Error "Invalid column name 'stManufacturerPartReference'."
So how can i use alias in where clause please help.
thanks.

I would do instead :
SELECT *, STUFF(stManufacturerPartReference, 1, 1, '') AS stManufacturerPartReference
FROM . . . .
. . . . CROSS APPLY
( SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM JOIN
tblProducts Product
ON PM.inProductId = Product.inProductId JOIN
tblManufacturers M
ON M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
FOR XML PATH('')
) tt(stManufacturerPartReference)
WHERE . . . AND
stManufacturerPartReference LIKE '%ABC DEF%';

You need to learn about the order of execution in a SQL query: https://sqlbolt.com/lesson/select_queries_order_of_execution
WHERE comes immediately after FROM, and therefore any aliases are not available to filter on.
As it's wrapped in a CTE, filter on stManufacturerPartReference in the query after it.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted 1
AND flgIsHistoricItem 1 AND (product.inCompanyId = 1) )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
WHERE P.stManufacturerPartReference LIKE '%ABC DEF%'
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;

You have to use outer apply or cross apply (select .. AS stManufacturerPartReference) and if your server is 2017 you could use String_AGG function to get list of values instead of for xml clause.

Related

Unable concate NULL value in SQL using CONCAT, COALESCE and ISNULL

I have a query with multiple joins where I want to combine records from two columns into one. If one column is empty then I want to show one column value as result. I tried with CONCAT, COALEASE and ISNULL but no luck. What am I missing here?
My objective is, create one column which has combination of s.Script AS Original and FromAnotherTable from query. Below query runs but throws Invalid column name 'Original' and Invalid column name 'FromAnotherTable'. when I try to use CONCAT, COALEASE or ISNULL .
SQL Query:
SELECT DISTINCT
c.Name AS CallCenter,
LTRIM(RTRIM(s.Name)) Name,
d.DNIS,
s.ScriptId,
s.Script AS Original,
(
SELECT TOP 5 CCSL.Line+'; '
FROM CallCenterScriptLine CCSL
WHERE CCSL.ScriptId = s.ScriptId
ORDER BY ScriptLineId FOR XML PATH('')
) AS FromAnotherTable,
--CONCAT(s.Script, SELECT TOP 5 CCSL.Line+'; ' FROM dbo.CallCenterScriptLine ccsl WHERE ccsl.ScriptId = s.ScriptId ORDER BY ccsl.ScriptLineId xml path(''))
--CONCAT(Original, FromAnotherTable) AS Option1,
--COALESCE(Original, '') + FromAnotherTable AS Option2,
--ISNULL(Original, '') + FromAnotherTable AS Option3,,
r.UnitName AS Store,
r.UnitNumber
FROM CallCenterScript s WITH (NOLOCK)
INNER JOIN CallCenterDNIS d WITH (NOLOCK) ON d.ScriptId = s.ScriptId
INNER JOIN CallCenter c WITH (NOLOCK) ON c.Id = s.CallCenterId
INNER JOIN CallCenterDNISRestaurant ccd WITH (NOLOCK) ON ccd.CallCenterDNISId = d.CallCenterDNISId
INNER JOIN dbo.Restaurant r WITH (NOLOCK) ON r.RestaurantID = ccd.CallCenterRestaurantId
WHERE c.Id = 5
AND (1 = 1)
AND (s.IsDeleted = 0 OR s.IsDeleted IS NULL)
ORDER BY DNIS ASC;
Output:
This works:
DECLARE #Column1 VARCHAR(50) = 'Foo',
#Column2 VARCHAR(50) = NULL;
SELECT CONCAT(#Column1,#Column2);
SELECT COALESCE(#Column2, '') + #Column1
SELECT ISNULL(#Column2, '') + #Column1
So I am not sure what I am missing in my original query.
Look at row 3 in the results you are getting. In your concatenated columns (Option1, 2, 3) you are getting the first script column twice. Not the first one + the second one like you expect.
The reason is because you've aliased your subquery "script" which is the same name as another column in your query, which makes it ambiguous.
Change the alias of the subquery and the problem should go away. I'm frankly surprised your query didn't raise an error.
EDIT: You can't use a column alias in another column's definition in the same level of the query. In other words, you can't do this:
SELECT
SomeColumn AS A
, (Subquery that returns a column) AS B
, A + B --this is not allowed
FROM ...
You can either create a CTE that returns the aliased columns and then concatenate them in the main query that selects from the CTE, or you have to use the original sources of the aliases, like so:
SELECT
SomeColumn AS A
, (Subquery that returns a column) AS B
, SomeColumn + (Subquery that returns a column) --this is fine
FROM ...
I took another approach where instead on creating separate column, I used ISNULL in my subQuery which returns my desired result.
Query:
SELECT DISTINCT
c.Name AS CallCenter,
LTRIM(RTRIM(s.Name)) Name,
d.DNIS,
s.ScriptId,
s.Script AS Original,
(
SELECT TOP 5 ISNULL(CCSL.Line, '')+'; ' + ISNULL(s.Script, '')
FROM CallCenterScriptLine CCSL
WHERE CCSL.ScriptId = s.ScriptId
ORDER BY ScriptLineId FOR XML PATH('')
) AS FromAnotherTable,
r.UnitName AS Store,
r.UnitNumber
FROM CallCenterScript s WITH (NOLOCK)
INNER JOIN CallCenterDNIS d WITH (NOLOCK) ON d.ScriptId = s.ScriptId
INNER JOIN CallCenter c WITH (NOLOCK) ON c.Id = s.CallCenterId
INNER JOIN CallCenterDNISRestaurant ccd WITH (NOLOCK) ON ccd.CallCenterDNISId = d.CallCenterDNISId
INNER JOIN dbo.Restaurant r WITH (NOLOCK) ON r.RestaurantID = ccd.CallCenterRestaurantId
WHERE c.Id = 5
AND (1 = 1)
AND (s.IsDeleted = 0 OR s.IsDeleted IS NULL)
ORDER BY DNIS ASC;
Here's a simplified example using table variables.
Instead of using a subquery for a field, it uses a CROSS APPLY.
And CONCAT in combination with STUFF is used to glue the strings together.
declare #Foo table (fooID int identity(1,1) primary key, Script varchar(30));
declare #Bar table (barID int identity(1,1) primary key, fooID int, Line varchar(30));
insert into #Foo (Script) values
('Test1'),('Test2'),(NULL);
insert into #Bar (fooID, Line) values
(1,'X'),(1,'Y'),(2,NULL),(3,'X'),(3,'Y');
select
f.fooID,
f.Script,
x.Lines,
CONCAT(Script+'; ', STUFF(x.Lines,1,2,'')) as NewScript
from #Foo f
cross apply (
select '; '+b.Line
from #Bar b
where b.fooID = f.fooID
FOR XML PATH('')
) x(Lines)
Result:
fooID Script Lines NewScript
----- ------- ------- -----------
1 Test1 ; X; Y Test1; X; Y
2 Test2 NULL Test2;
3 NULL ; X; Y X; Y

I Inherited a complicated SSRS report that uses a query to grab information about our projects

So I have this query driven ssrs report and I have been asked on part of the report to list the engineers that billed the most hours to the project list them in order from most to least... max to min. This is the huge Query.
declare #startDate date
declare #endDate date
set #startDate = GETDATE() -30
set #endDate = GETDATE()
SELECT
PN_B,
PN_A,
Project_Practice,
Date_Closed_UTC,
Project_ID,
Company_Name,
Invoiced_Service_Amount,
AGR_Amt,
Total_Service_Billing,
Project_TCW,
Hrs_Budgeted,
Est_Hours,
Billing_Method,
Project_Total_Hrs,
Project_Hrs_B,
Project_Hrs_NB,
Project_Hrs_NC,
Project_Hrs_Agr,
Project_Status,
Location,
OPP_RECID,
Opportunity_RecID,
AM,
DA,
PM,
PeopleNRole,
PM_Billing_Method_ID
FROM
(
SELECT
PPRS2.PN_B,
PPRS2.PN_A,
PPRS2.Project_Practice,
PPRS2.Date_Closed_UTC,
PPRS2.Project_ID,
PPRS2.Company_Name,
PPRS2.Invoiced_Service_Amount,
PPRS2.AGR_Amt,
PPRS2.Total_Service_Billing,
PPRS2.Project_TCW,
PPRS2.Hrs_Budgeted,
PPRS2.Est_Hours,
PPRS2.Billing_Method,
PPRS2.Project_Total_Hrs,
PPRS2.Project_Hrs_B,
PPRS2.Project_Hrs_NB,
PPRS2.Project_Hrs_NC,
PPRS2.Project_Hrs_Agr,
PPRS2.Project_Status,
PPRS2.Location,
PPRS2.OPP_RECID,
AMDA2.Opportunity_RecID,
AMDA2.AM,
AMDA2.DA,
AMDA2.PM,
PeopleNRole,
PPRS2.PM_BILLING_METHOD_ID
FROM
(
SELECT
PN_B,
PN_A,
Project_Practice,
Date_Closed_UTC,
Project_ID,
Company_Name,
Invoiced_Service_Amount,
AGR_Amt,
Total_Service_Billing,
Project_TCW,
Hrs_Budgeted,
Est_Hours,
Billing_Method,
Project_Total_Hrs,
Project_Hrs_B,
Project_Hrs_NB,
Project_Hrs_NC,
Project_Hrs_Agr,
Project_Status,
Location,
OPP_RECID,
pl2.PeopleNRole,
PM_Billing_Method_ID
FROM
(
SELECT
Table_B.Project_Number AS PN_B,
Table_A.Project_Number AS PN_A,
Table_A.Project_Practice,
Table_A.Date_Closed_UTC,
Table_A.Project_ID,
Table_A.Company_Name,
Table_A.Invoiced_Service_Amount,
Table_A.AGR_Amt,
Table_A.Total_Service_Billing,
Table_B.Project_TCW,
Table_A.Hrs_Budgeted,
Table_A.Est_Hours,
Table_A.Billing_Method,
Table_B.Project_Total_Hrs,
Table_B.Project_Hrs_B,
Table_B.Project_Hrs_NB,
Table_B.Project_Hrs_NC,
Table_B.Project_Hrs_Agr,
Table_A.Project_Status,
Table_A.Location,
Table_A.OPP_RECID,
Table_A.PM_BILLING_METHOD_ID
FROM
(
SELECT
Total_Service_Billing,
AGR_Amt,
Invoiced_Service_Amount,
Sales_Tax_Amount_Total,
Project_Number,
Project_ID,
Date_Closed_UTC,
Est_Hours,
Billing_Method,
Company_Name,
Project_Status,
Project_Practice,
Hrs_Budgeted,
Location,
OPP_RECID,
PM_Billing_Method_ID
FROM
(
SELECT
Project_Service_Totals.Service_Total AS Total_Service_Billing,
Project_Service_Totals.AGR_Amt,
Project_Service_Totals.Service_Invoice_Amt_Total AS Invoiced_Service_Amount,
Project_Service_Totals.Sales_Tax_Amount_Total,
Project_Service_Totals.Project_RecID AS Project_Number,
PM_Project.Project_ID,
PM_Project.Date_Closed_UTC,
PM_Project.Est_Hours,
PM_Project.PM_Billing_Method_ID AS Billing_Method, /* A = Actual Rates F = Fixed Fee for the Inital Project Type */
Company.Company_Name,
PM_Status.Description AS Project_Status,
PM_Type.Description AS Project_Practice,
SUM(v_rpt_Project.hours_budget) AS Hrs_Budgeted,
Owner_Level.Description AS Location,
PM_Project.Opportunity_RecID AS OPP_RECID,
PM_Project.PM_Billing_Method_ID
FROM
(
SELECT
SUM(Service_Invoice_Amt - Sales_Tax) + SUM(BL_AGR_AMT) AS Service_Total,
SUM(BL_AGR_AMT) AS AGR_Amt,
SUM(Service_Invoice_Amt) AS Service_Invoice_Amt_Total,
SUM(Sales_Tax) AS Sales_Tax_Amount_Total,
Project_RecID
FROM
(
SELECT
Billing_Log_RecID,
Invoice_Number,
Invoice_Amount AS Service_Invoice_Amt,
PM_Project_RecID AS Project_RecID,
Sales_Tax_Amount AS Sales_Tax,
AGR_Amount AS BL_AGR_AMT
FROM
Billing_Log AS Billing_Log_1
)
AS Service_Invoice_Total
GROUP BY Project_RecID
)
AS Project_Service_Totals
INNER JOIN
PM_Project
ON
Project_Service_Totals.Project_RecID = PM_Project.PM_Project_RecID
INNER JOIN
Company
ON
PM_Project.Company_RecID = Company.Company_RecID
INNER JOIN
PM_Status
ON
PM_Project.PM_Status_RecID = PM_Status.PM_Status_RecID
INNER JOIN
PM_Type
ON
PM_Project.PM_Type_RecID = PM_Type.PM_Type_RecID
INNER JOIN
v_rpt_Project
ON
PM_Project.PM_Project_RecID = v_rpt_Project.ProjectNbr
INNER JOIN
Owner_Level
ON
PM_Project.Owner_Level_RecID = Owner_Level.Owner_Level_RecID
GROUP BY
Project_Service_Totals.Service_Total,
Project_Service_Totals.AGR_Amt,
Project_Service_Totals.Service_Invoice_Amt_Total,
Project_Service_Totals.Sales_Tax_Amount_Total,
Project_Service_Totals.Project_RecID,
PM_Project.Project_ID,
PM_Project.Date_Closed_UTC,
PM_Project.Est_Hours,
PM_Project.PM_Billing_Method_ID,
Company.Company_Name,
PM_Status.Description,
PM_Type.Description,
Owner_Level.Description,
PM_Project.Opportunity_RecID
)
AS T
)
AS Table_A
INNER JOIN
(
SELECT
Project_Hrs_B,
Project_Hrs_NB,
Project_Hrs_NC,
Project_Total_Hrs,
Project_Hrs_Agr,
Project_TCW,
Project_Number
FROM
(
SELECT
SUM(Hrs_Billable) AS Project_Hrs_B,
SUM(Hrs_NonBillable) AS Project_Hrs_NB,
SUM(Hrs_NoCharge) AS Project_Hrs_NC,
SUM(Hrs_Billable + Hrs_NonBillable + Hrs_NoCharge) AS Project_Total_Hrs,
SUM(Hrs_Agr) AS Project_Hrs_Agr,
SUM(Project_TC) AS Project_TCW,
Project_Number
FROM
(
SELECT
SUM(Hrs_B) AS Hrs_Billable,
SUM(Hrs_NB) AS Hrs_NonBillable,
SUM(Hrs_NC) AS Hrs_NoCharge,
SUM(Agr_Hrs) AS Hrs_Agr,
SUM(TE_TotalCost) AS Project_TC,
Project_Number,
REC_ID,
Full_Name
FROM
(
SELECT
Rec_ID,
Full_Name,
Project_Number,
SUM(VT_Hrs_Agr) AS Agr_Hrs,
SUM(Line_TC) AS TE_TotalCost,
SUM(CASE WHEN Billing_Type = 'B' THEN (TE_Hrs_Inv) ELSE 0 END) AS Hrs_B,
SUM(CASE WHEN Billing_Type = 'NB' THEN (TE_Hrs_Inv) ELSE 0 END) AS Hrs_NB,
SUM(CASE WHEN Billing_Type = 'NC' THEN (TE_Hrs_Inv) ELSE 0 END) AS Hrs_NC
FROM
(
SELECT
VT_Hrs_Cost,
TE_Hrs_Inv,
Line_TC,
VT_Hrs_B,
VT_Hrs_NB,
VT_Hrs_Agr,
Project_Number,
Rec_ID,
Full_Name,
Billing_Type,
Work_Role
FROM
(
SELECT
v_rpt_Time.Hourly_Cost AS VT_Hrs_Cost,
Time_Entry.Hours_Invoiced AS TE_Hrs_Inv,
v_rpt_Time.Hourly_Cost * Time_Entry.Hours_Invoiced AS Line_TC,
v_rpt_Time.Billable_Hrs AS VT_Hrs_B,
v_rpt_Time.NonBillable_Hrs AS VT_Hrs_NB,
v_rpt_Time.AgrHrsCovered AS VT_Hrs_Agr,
Time_Entry.PM_Project_RecID AS Project_Number,
v_rpt_Time.member_recid AS Rec_ID,
v_rpt_Time.first_name + ' ' + v_rpt_Time.last_name AS Full_Name,
v_rpt_Time.option_id AS Billing_Type,
v_rpt_Time.work_role AS Work_Role
FROM
Time_Entry
INNER JOIN
v_rpt_Time
ON
Time_Entry.Time_RecID = v_rpt_Time.Time_RecID
)
AS Project_Hrs
)
AS Project_Hrs_Sorted
GROUP BY
Project_Number,
Billing_Type,
TE_Hrs_Inv,
VT_Hrs_Agr,
Rec_ID,
Full_Name
)
AS Project_Cost
GROUP BY
Project_Number,
Rec_ID,
Full_Name
)
AS Project_Totals
GROUP BY
Project_Number
)
AS B
)
AS Table_B
ON
Table_A.Project_Number = Table_B.Project_Number
) AS PPRS,
/* Section that creates the Column to Row using a CROSS APPLY and STUFF Command with XML */
(
SELECT
Project_Number,
PeopleNRole
FROM
(
SELECT DISTINCT
Base.PeopleNrole,
p1.Project_Number
FROM
(
SELECT DISTINCT
Time_Entry10.PM_Project_RecID AS Project_Number,
(v_rpt_Time10.first_name + ' ' + v_rpt_Time10.last_name /* + ' ' + member10.Role_id Removes the SE from the Name*/) AS PeopleNrole,
Member10.Role_ID AS RoleID
FROM
Time_Entry AS Time_Entry10
INNER JOIN
v_rpt_Time AS v_rpt_Time10
ON
Time_Entry10.Time_RecID = v_rpt_Time10.Time_RecID
INNER JOIN
Member AS Member10
ON
v_rpt_Time10.member_recid = Member10.Member_RecID AND Member10.Role_ID = 'SE'
--order by Time_Entry10.Hours_Bill desc
)
AS P1
CROSS APPLY
(
SELECT
STUFF
(
(
SELECT ', ' + PeopleNrole
FROM
(
SELECT DISTINCT
Time_Entry11.PM_Project_RecID AS Project_Number,
(v_rpt_Time11.first_name + ' ' + v_rpt_Time11.last_name/* + ' ' + member11.Role_id Removes the SE from the Name*/ ) AS PeopleNrole,
Member11.Role_ID
AS
RoleID
FROM
Time_Entry
AS
Time_Entry11
INNER JOIN
v_rpt_Time AS v_rpt_Time11
ON
Time_Entry11.Time_RecID = v_rpt_Time11.Time_RecID
INNER JOIN
Member AS Member11
ON
v_rpt_Time11.member_recid = Member11.Member_RecID AND Member11.Role_ID = 'SE'
--order by Time_Entry11.Hours_Bill desc
)
AS
P2
WHERE
p2.Project_Number = P1.Project_Number
ORDER BY
Time_Entry.Hours_Bill
FOR
XML
PATH(''), TYPE ).value('.', 'varchar(max)'), 1, 1, '')) Base(PeopleNRole))
AS PeopleLink
)
AS pl2
WHERE
PPRS.PN_A = PL2.Project_Number
)
AS PPRS2
INNER JOIN
(
SELECT
Opportunity_RecID,
AM,
DA,
PM
FROM
(
SELECT
N.Opportunity_RecID,
Member_1.First_Name + ' ' + Member_1.Last_Name AS AM,
Member_2.First_Name + ' ' + Member_2.Last_Name AS DA,
Member_3.First_Name + ' ' + Member_3.Last_Name AS PM
FROM
Member AS Member_1
INNER JOIN
(
SELECT DISTINCT
v_rpt_Opportunity3.Opportunity_RecID,
v_rpt_Opportunity3.Sales_Rep1,
v_rpt_Opportunity3.Sales_Rep2,
PM_Project3.Member_ID
FROM
v_rpt_Opportunity AS v_rpt_Opportunity3
INNER JOIN
PM_Project AS PM_Project3
ON
v_rpt_Opportunity3.Opportunity_RecID = PM_Project3.Opportunity_RecID
) AS N
ON
Member_1.Member_ID = N.Sales_Rep1
INNER JOIN
Member AS Member_2
ON
N.Sales_Rep2 = Member_2.Member_ID
INNER JOIN
Member AS Member_3
ON
N.Member_ID = Member_3.Member_ID
)
AS AMDA
)
AS AMDA2
ON
PPRS2.OPP_RECID = AMDA2.Opportunity_RecID
)
AS PPRS_pt1
WHERE
Date_Closed_UTC BETWEEN #Startdate AND #EndDate
AND
Location <> 'AOSCloud'
/* (Location IN(#Division))
AND Per Leslie 8/14/2013 want all divisions listed
(Project_Practice = IN (#Practice)*/
ORDER BY PN_B
I have committed out kind of where I think I needed to edit the query timeentry10 and timeentry11 but I cant do this because order by clause is invalid in views, inline functions, derived tables, subqueries and common table expressions, unless top, offset,or for xml is also specified... So what I did was try to do time_entry.hours_bill desc but it is telling me that I do not have access to the time_entry at that position. What they had before is order by roleid before the for xml. this really has me thrown off because I feel it is over complicated. Any help with this would be great. I also would not be opposed to take the peoplenrole add another column and just get the person with the most hours and add it to the report saying SE with most hours for the business.
the section that gets the peoplenrole is this
* Section that creates the Column to Row using a CROSS APPLY and STUFF Command with XML */
(
SELECT
Project_Number,
PeopleNRole
FROM
(
SELECT DISTINCT
Base.PeopleNrole,
p1.Project_Number
FROM
(
SELECT DISTINCT
Time_Entry10.PM_Project_RecID AS Project_Number,
(v_rpt_Time10.first_name + ' ' + v_rpt_Time10.last_name /* + ' ' + member10.Role_id Removes the SE from the Name*/) AS PeopleNrole,
Member10.Role_ID AS RoleID
FROM
Time_Entry AS Time_Entry10
INNER JOIN
v_rpt_Time AS v_rpt_Time10
ON
Time_Entry10.Time_RecID = v_rpt_Time10.Time_RecID
INNER JOIN
Member AS Member10
ON
v_rpt_Time10.member_recid = Member10.Member_RecID AND Member10.Role_ID = 'SE'
--order by Time_Entry10.Hours_Bill desc
)
AS P1
CROSS APPLY
(
SELECT
STUFF
(
(
SELECT ', ' + PeopleNrole
FROM
(
SELECT DISTINCT
Time_Entry11.PM_Project_RecID AS Project_Number,
(v_rpt_Time11.first_name + ' ' + v_rpt_Time11.last_name/* + ' ' + member11.Role_id Removes the SE from the Name*/ ) AS PeopleNrole,
Member11.Role_ID
AS
RoleID
FROM
Time_Entry
AS
Time_Entry11
INNER JOIN
v_rpt_Time AS v_rpt_Time11
ON
Time_Entry11.Time_RecID = v_rpt_Time11.Time_RecID
INNER JOIN
Member AS Member11
ON
v_rpt_Time11.member_recid = Member11.Member_RecID AND Member11.Role_ID = 'SE'
--order by Time_Entry11.Hours_Bill desc
)
AS
P2
WHERE
p2.Project_Number = P1.Project_Number
ORDER BY
RoleID
FOR
XML
PATH(''), TYPE ).value('.', 'varchar(max)'), 1, 1, '')) Base(PeopleNRole))
AS PeopleLink
)
AS pl2
WHERE
PPRS.PN_A = PL2.Project_Number
)
here is a pic of the data
So quick and dirty I found an SSRS report obviously this same person did that calculated these hours like this
SELECT F_Name, L_Name, Total_TE_Hours_Actual, project_id
FROM (SELECT SUM(TE_Part2.TE_Hours_Actual) AS Total_TE_Hours_Actual, Member.First_Name AS F_Name, Member.Last_Name AS L_Name, TE_Part2.PM_Project_RecID as project_id
FROM
(SELECT TE_Hours_Actual, PM_Project_RecID, Rec_ID
FROM
(SELECT v_rpt_Time.Hourly_Cost AS TE_Hourly_Cost, v_rpt_Time.hours_actual AS TE_Hours_Actual, Time_Entry.PM_Project_RecID, v_rpt_Time.NonBillable_Hrs AS TE_Hours_Non_Billable, v_rpt_Time.member_recid AS Rec_ID
FROM Time_Entry
INNER JOIN v_rpt_Time ON Time_Entry.Time_RecID = v_rpt_Time.Time_RecID
) AS TE_Part1) AS TE_Part2
INNER JOIN Member ON TE_Part2.Rec_ID = Member.Member_RecID
GROUP BY TE_Part2.Rec_ID, Member.First_Name, Member.Last_Name, TE_Part2.PM_Project_RecID) AS TE_Part3
so I put this to a CTE like this
with time_CTE(F_Name, L_Name, Total_TE_Hours_Actual, project_id) as (
SELECT F_Name, L_Name, Total_TE_Hours_Actual, project_id
FROM (SELECT SUM(TE_Part2.TE_Hours_Actual) AS Total_TE_Hours_Actual, Member.First_Name AS F_Name, Member.Last_Name AS L_Name, TE_Part2.PM_Project_RecID as project_id
FROM
(SELECT TE_Hours_Actual, PM_Project_RecID, Rec_ID
FROM
(SELECT v_rpt_Time.Hourly_Cost AS TE_Hourly_Cost, v_rpt_Time.hours_actual AS TE_Hours_Actual, Time_Entry.PM_Project_RecID, v_rpt_Time.NonBillable_Hrs AS TE_Hours_Non_Billable, v_rpt_Time.member_recid AS Rec_ID
FROM Time_Entry
INNER JOIN v_rpt_Time ON Time_Entry.Time_RecID = v_rpt_Time.Time_RecID
) AS TE_Part1) AS TE_Part2
INNER JOIN Member ON TE_Part2.Rec_ID = Member.Member_RecID
GROUP BY TE_Part2.Rec_ID, Member.First_Name, Member.Last_Name, TE_Part2.PM_Project_RecID) AS TE_Part3)
select top 1 f_name + ' ' + l_name as Name, total_TE_Hours_Actual, project_id from time_CTE
where project_id is not null
order by Total_TE_Hours_Actual desc;
I made a new column in my ssrs that said top SE then I did a lookup like this
=lookup (Fields!PN_A.value, Fields!project_id.value, Fields!Name.value, "SETime")
so this satisfied the business user, but I am taking the advice I got here and breaking that main query up into CTEs that thing is way to ugly

SQL Stuff from Subquery

I have a query that returns a list of services and ContractorIDs. I need to stuff these services into a field to join them with another select statement by ContractorID, but I can't figure out how to do it.
The Select that lists the services is "
SELECT DISTINCT SM.ContractorID,
CASE WHEN S.bitRestrictedSelection = 1
THEN S.vchDescription + '*'
ELSE S.vchDescription
END AS vchDescription
FROM tblAscServiceRegionToOperator SRTO
INNER JOIN tblServiceMatrix SM
ON SRTO.OperatorID = 12624
AND SM.ServiceRegionID = SRTO.ServiceRegionID
AND SM.bitPrimaryService = 1
INNER JOIN tblServices S
ON S.ServiceID = SM.ServiceID
This produces the following:
In the example, for Contractor #16 He has 4 services I need to put them in one field called services by joining with another Select statement
I tried the following, but I get errors:
Select DISTINCT CompanyID, vchCompanyName as CompanyName,vchFIDNumber,vchPrimContactName, vchPrimContactEmail
,stuff((','
SELECT DISTINCT
SM.ContractorID,
CASE WHEN S.bitRestrictedSelection = 1
THEN S.vchDescription + '*'
ELSE S.vchDescription
END AS vchDescription
FROM tblAscServiceRegionToOperator SRTO
INNER JOIN tblServiceMatrix SM
ON SRTO.OperatorID = 12624
AND SM.ServiceRegionID = SRTO.ServiceRegionID
AND SM.bitPrimaryService = 1
INNER JOIN tblServices S
ON S.ServiceID = SM.ServiceID
FOR XML PATH('')
), 1, 1, '') as Services from tblCompany
Any assistance is greatly appreciated!!!
The following query would work:
SELECT SS.contractor Contractor,
STUFF((SELECT '; ' + US.vchdescription
FROM ServicesList US
WHERE US.contractor = SS.contractor
FOR XML PATH('')), 1, 1, '') [Services]
FROM ServicesList SS
GROUP BY SS.contractor
ORDER BY 1
I have created a table and inserted there two rows for contractor = 16, for you to get the idea.
You can use the suggestion given to you in the comments, to wrap the first select into a CTE and then perform the STUFF function on that CTE.
You can check a demo of this query here.

Create View - Declare a variable

I am creating a view that is using that STUFF function. I want to put the result of STUFF in a variable for my view. The problem I am having is declaring my variable. It gives me the message "Incorrect Syntax near 'DECLARE'. Expecting '(' or SELECT." I already have the '(' in there. I have tried putting a BEGIN before it. I have tried putting it after the SELECT word. But nothing seems to work and I cannot find a solution in my search. I am using SQL Server 2012
CREATE VIEW [AQB_OB].[GISREQUESTEDBURNS]
AS
(DECLARE #CONDITIONS AS varchar(20)
SET #CONDITIONS = (SELECT DISTINCT BD.[RequestedBurnsID]
,[ConditionsReasonsID] = STUFF((SELECT ', ' + CONVERT(VARCHAR (20),[ConditionsReasonsID]) FROM [AQB_OB].[BurnDecisions] WHERE [RequestedBurnsID]= BD.[RequestedBurnsID] ORDER BY [RequestedBurnsID] ASC
FOR XML PATH ('')) , 1 , 1, '') FROM
[AQB_OB].[BurnDecisions] BD)
SELECT RB.[RequestedBurnsID] AS REQUESTEDBURNID
,BUY.[BurnYear] AS BURNYEAR
,CY.[CurrentYear] AS CURRENTYEAR
,RB.[BurnSitesID] AS BURNSITESID
,[BurnerID] AS BURNERID
,[Contact] AS CONTACT
,[BurnDecision] AS BURNDECISION
,RB.[Comment] AS COMMENT
,#CONDITIONS AS CONDITIONS
FROM [AQB_MON].[AQB_OB].[RequestedBurns] RB
LEFT join AQB_MON.[AQB_OB].[PileDryness] PD on RB.[PileDrynessID] = PD.[PileDrynessID]
inner join AQB_MON.[AQB_OB].[BurnYear] BUY on BUY.BurnYearID = BP.BurnYearID
inner join AQB_MON.[AQB_OB].[CurrentYear] CY on CY.CurrentYearID = BUY.CurrentYearID
GO
You can't declare variables in a view. Could you make it into a function or stored procedure?
Edit - you might also be able to put something into a CTE (Common Table Expression) and keep it as a view.
e.g.
WITH conditions as
(
... do the STUFF here
)
SELECT blah
FROM blah
INNER JOIN conditions
(or CROSS JOIN conditions if its just one row, I can't quite decipher what your data is like)
Here is a sample query that uses a CTE (Common Table Expression) to nicely emulate internal variable construction, as described by James Casey. You can test-run it in your version of SQL Server.
CREATE VIEW vwImportant_Users AS
WITH params AS (
SELECT
varType='%Admin%',
varMinStatus=1)
SELECT status, name
FROM sys.sysusers, params
WHERE status > varMinStatus OR name LIKE varType
SELECT * FROM vwImportant_Users
yielding output:
status name
12 dbo
0 db_accessadmin
0 db_securityadmin
0 db_ddladmin
also via JOIN
WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name
FROM sys.sysusers INNER JOIN params ON 1=1
WHERE status > varMinStatus OR name LIKE varType
also via CROSS APPLY
WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name
FROM sys.sysusers CROSS APPLY params
WHERE status > varMinStatus OR name LIKE varType
Or use a CTE (common table expression) as subselect like:
WITH CTE_Time(Clock)
AS(
SELECT 11 AS [Clock] -- set var
)
SELECT
DATEPART(HOUR, GETDATE()) AS 'actual hour',
CASE
WHEN DATEPART(HOUR, GETDATE()) >= (SELECT [Clock] FROM CTE_Time) THEN 'after'
ELSE 'before'
END AS [Data]
Try put the condition subquery directly inside the the view select statement. you may CAST the XML to VARCHAR(20).
CREATE VIEW [AQB_OB].[GISREQUESTEDBURNS]
AS
SELECT RB.[RequestedBurnsID] AS REQUESTEDBURNID
,BUY.[BurnYear] AS BURNYEAR
,CY.[CurrentYear] AS CURRENTYEAR
,RB.[BurnSitesID] AS BURNSITESID
,[BurnerID] AS BURNERID
,[Contact] AS CONTACT
,[BurnDecision] AS BURNDECISION
,RB.[Comment] AS COMMENT,
(
SELECT DISTINCT BD.[RequestedBurnsID],
[ConditionsReasonsID] = STUFF((SELECT ', ' + CONVERT(VARCHAR (20), [ConditionsReasonsID]) FROM [AQB_OB].[BurnDecisions]
WHERE [RequestedBurnsID]= BD.[RequestedBurnsID] ORDER BY [RequestedBurnsID] ASC
FOR XML PATH ('')) , 1 , 1, '') FROM
[AQB_OB].[BurnDecisions] BD
) AS CONDITIONS
FROM [AQB_MON].[AQB_OB].[RequestedBurns] RB
LEFT join AQB_MON.[AQB_OB].[PileDryness] PD on RB.[PileDrynessID] = PD.[PileDrynessID]
inner join AQB_MON.[AQB_OB].[BurnYear] BUY on BUY.BurnYearID = BP.BurnYearID
inner join AQB_MON.[AQB_OB].[CurrentYear] CY on CY.CurrentYearID = BUY.CurrentYearID

SQL Server 2014 "for xml path" into View

I have a query that works well on its own, putting multiple values into a single column:
select substring(
(
select '/'+ Convert(nvarchar,OE) AS 'data()'
from wpb1.dbo.OE_table
where QDBID = 605441478
for xml path('')
)
,2, 255) as list1
And I have this View that I want to put it into, which works fine on its own:
SELECT
DISTINCT wpb1.dbo.Quotes.[Quote Num], MIN(wpb1.dbo.OE_table.OE) AS [Min OE],
COUNT(wpb1.dbo.OE_table.OE) AS [Count OE]
FROM wpb1.dbo.Quotes
LEFT OUTER JOIN wpb1.dbo.OE_table
ON wpb1.dbo.Quotes.QuoteDBID = wpb1.dbo.OE_table.QDBID
GROUP BY wpb1.dbo.Quotes.[Quote Num]
But when I try it causes an error saying:
Error in WHERE clause near '('. Error in GROUP BY clause. Unable to
parse query text.
This is what I am trying:
SELECT
DISTINCT wpb1.dbo.Quotes.[Quote Num], MIN(wpb1.dbo.OE_table.OE) AS [Min OE],
COUNT(wpb1.dbo.OE_table.OE) AS [Count OE],
(
select substring(
(
select '/'+ Convert(nvarchar,OE) AS 'data()'
from wpb1.dbo.OE_table
where QDBID = 605441478
for xml path('')
),2, 255)
) as list1
FROM wpb1.dbo.Quotes LEFT OUTER JOIN wpb1.dbo.OE_table
ON wpb1.dbo.Quotes.QuoteDBID = wpb1.dbo.OE_table.QDBID
GROUP BY wpb1.dbo.Quotes.[Quote Num]
What am I doing wrong?
Using SQL Server 2014.

Resources