2

This is my query:

SELECT
    wp.WorkplanID,
    STUFF((SELECT ', ' + ISNULL(ul.FirstName + ' ', '') + ISNULL(ul.LastName, '')
           FROM UserLogin ul
           INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
           INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
           WHERE wpv.WorkPlanID = wp.WorkPlanID
           FOR XML PATH('')), 1, 2, '') AS VendorName,
    STUFF((SELECT ', ' + v.PrimaryPhone
           FROM UserLogin ul
           INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
           INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
           WHERE wpv.WorkPlanID = wp.WorkPlanID
           FOR XML PATH('')), 1, 2, '') AS PrimaryPhone,
    STUFF((SELECT ', ' + ul.Email
           FROM UserLogin ul
           INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
           INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
           WHERE wpv.WorkPlanID = wp.WorkPlanID
           FOR XML PATH('')), 1, 2, '') AS Email
FROM WorkPlan wp

It is taking 5 seconds to get data but I want to make it faster.

5
  • Upgrading to 2017 for STRING_AGG so you don't need 3 subqueries would be an excellent start. Commented Sep 14, 2023 at 12:57
  • You might find that forcing your XML to be returned as XML and then using the value method give a little performance benefit: ...FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(MAX)')... Commented Sep 14, 2023 at 13:04
  • 1
    fetching the joined data once and putting it in a temp table might also be a good idea. Might also try to remove the CAST(v.vendorID) thing Commented Sep 14, 2023 at 13:04
  • Didn't notice the CAST; why are the datatypes of VendorID different in WorkPlanVendors and Vendors? It appears you aren't getting an error, so there aren't invalid int values in Vendors, so fixing the data type would be of benefit as its makes the query SARGable. Commented Sep 14, 2023 at 13:05
  • plus, you might wanna use FOR XML TYPE, so your & < > in names doesn't mangle your xml strings Commented Sep 14, 2023 at 13:05

3 Answers 3

-1

You used the same query for three columns. You can use a common table expression to join the tables once and use this reference in your query as below:

WITH CTE_WorkPlanVendors AS (
    SELECT wpv.WorkPlanID AS VendorWorkPlanID, ul.FirstName, ul.LastName, v.PrimaryPhone, ul.Email
    FROM UserLogin ul
    INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
    INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
)
SELECT wp.WorkplanID,
       STUFF((SELECT ', ' + ISNULL(FirstName + ' ', '') + ISNULL(LastName, '')
              FROM CTE_WorkPlanVendors cte
              WHERE cte.VendorWorkPlanID = wp.WorkPlanID
              FOR XML PATH('')), 1, 2, '') AS VendorName,
       STUFF((SELECT ', ' + PrimaryPhone
              FROM CTE_WorkPlanVendors cte
              WHERE cte.VendorWorkPlanID = wp.WorkPlanID
              FOR XML PATH('')), 1, 2, '') AS PrimaryPhone,
       STUFF((SELECT ', ' + Email
              FROM CTE_WorkPlanVendors cte
              WHERE cte.VendorWorkPlanID = wp.WorkPlanID
              FOR XML PATH('')), 1, 2, '') AS Email
FROM WorkPlan wp;
Sign up to request clarification or add additional context in comments.

Comments

-1

The existing answers do not help as they all query the base table many times.

You can use the following solution to query the base table once and aggregate it up:

  • In an APPLY, use FOR XML PATH('row') to aggregate up the entire dataset into one XML. Add in the commas.
  • In the SELECT, query each column as follows:
    • .query('row/TheColumn/text()') this gets you all the text elements for that name.
    • .value('text()[1]', 'nvarchar(max)') this unescapes any XML encoding.
    • Use STUFF to strip off the leading comma.
SELECT
  wp.WorkplanID,
  STUFF(x.x.query('row/Name/text()'        ).value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS VendorName,
  STUFF(x.x.query('row/PrimaryPhone/text()').value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS PrimaryPhone,
  STUFF(x.x.query('row/Email/text()'       ).value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS Email
FROM (
    SELECT wp.WorkplanID
    FROM WorkPlan wp
    GROUP BY wp.WorkplanID
) wp
CROSS APPLY (
    SELECT
      ',' + ISNULL(FirstName + ' ', '') + ISNULL(LastName, '') AS Name
      ',' + v.PrimaryPhone AS PrimaryPhone,
      ',' + ul.Email AS Email
    FROM UserLogin ul
    INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
    INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
    WHERE wpv.WorkPlanID = wp.WorkPlanID
    FOR XML PATH('row')
) x(x);

Obviously in newer versions of SQL Server you don't need any of this, you can just use STRING_AGG.

Comments

-1
   ;

WITH CTE
AS (
    SELECT wp.WorkplanID
        ,ISNULL(ul.FirstName + ' ', '') + ISNULL(ul.LastName, '') AS FULLNAME
        ,v.PrimaryPhone
        ,ul.Email
    FROM WorkPlan wp
    INNER JOIN WorkPlanVendors wpv ON wpv.WorkPlanID = wp.WorkPlanID
    INNER JOIN Vendors v ON wpv.VendorID = CAST(v.VendorID AS INT)
    INNER JOIN UserLogin ul ON ul.UserLoginID = v.UserLoginID
    )
SELECT C.WorkplanID
    ,STUFF((
            SELECT ', ' + FULLNAME
            FROM CTE CFN
            WHERE C.WorkPlanID = CFN.WorkPlanID
            FOR XML PATH('')
            ), 1, 2, '') AS FULLNAME
    ,STUFF((
            SELECT ', ' + PrimaryPhone
            FROM CTE CPP
            WHERE C.WorkPlanID = CPP.WorkPlanID
            FOR XML PATH('')
            ), 1, 2, '') AS PrimaryPhone
    ,STUFF((
            SELECT ', ' + Email
            FROM CTE CEM
            WHERE C.WorkPlanID = CEM.WorkPlanID
            FOR XML PATH('')
            ), 1, 2, '') AS Email
FROM CTE C

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.