Home > other >  Combining data into one table cell
Combining data into one table cell

Time:11-09

There is a query that returns a temporary table. TSQL Query:

SELECT 
    CAST(SOH.OrderDate AS DATE) as DateYMD,
    P.LastName,
    P.FirstName,
    PP.[Name]   ' Qty: '   CAST(SOD.OrderQty AS varchar(10)) as [OrderContent]

FROM Person.Person as P
    JOIN Sales.Customer SC ON P.BusinessEntityID = SC.PersonID
    JOIN Sales.SalesOrderHeader as SOH ON SC.CustomerID = SOH.CustomerID
    AND SOH.SalesOrderID = (
        SELECT TOP 1 subSOH.SalesOrderID
        FROM Sales.SalesOrderHeader as subSOH
        WHERE subSOH.CustomerID = SOH.CustomerID
        ORDER BY subSOH.OrderDate DESC 
    )
    JOIN Sales.SalesOrderDetail as SOD ON SOH.SalesOrderID = SOD.SalesOrderID
    JOIN Production.Product as PP ON SOD.ProductID = PP.ProductID

Result: Random sampling of output values

Is it possible to group data from the last column, thereby reducing the number of lines in the output. That is, I need it to be like this: Desired result

UPD: SQL Server 2016. STRING_AGG is missing

CodePudding user response:

Group by the values you need (DateYMD,LastName,FirstName) and STRING_AGG can do this

Select DateYMD,LastName,FirstName, STRING_AGG(OrderContent,';') order_contents from
(
SELECT 
    CAST(SOH.OrderDate AS DATE) as DateYMD,
    P.LastName,
    P.FirstName,
    PP.[Name]   ' Qty: '   CAST(SOD.OrderQty AS varchar(10)) as [OrderContent]

FROM Person.Person as P
    JOIN Sales.Customer SC ON P.BusinessEntityID = SC.PersonID
    JOIN Sales.SalesOrderHeader as SOH ON SC.CustomerID = SOH.CustomerID
    AND SOH.SalesOrderID = (
        SELECT TOP 1 subSOH.SalesOrderID
        FROM Sales.SalesOrderHeader as subSOH
        WHERE subSOH.CustomerID = SOH.CustomerID
        ORDER BY subSOH.OrderDate DESC 
    )
    JOIN Sales.SalesOrderDetail as SOD ON SOH.SalesOrderID = SOD.SalesOrderID
    JOIN Production.Product as PP ON SOD.ProductID = PP.ProductID ) q 
    group by DateYMD,LastName,FirstName

STUFF FOR XML PATH for sqlserver 16 :

WITH tbl (DateYMD, LastName, FirstName ,  OrderContent)  
AS  
(  -- it is your query
SELECT 
    CAST(SOH.OrderDate AS DATE) as DateYMD,
    P.LastName,
    P.FirstName,
    PP.[Name]   ' Qty: '   CAST(SOD.OrderQty AS varchar(10)) as [OrderContent]
FROM Person.Person as P
    JOIN Sales.Customer SC ON P.BusinessEntityID = SC.PersonID
    JOIN Sales.SalesOrderHeader as SOH ON SC.CustomerID = SOH.CustomerID
    AND SOH.SalesOrderID = (
        SELECT TOP 1 subSOH.SalesOrderID
        FROM Sales.SalesOrderHeader as subSOH
        WHERE subSOH.CustomerID = SOH.CustomerID
        ORDER BY subSOH.OrderDate DESC 
    )
    JOIN Sales.SalesOrderDetail as SOD ON SOH.SalesOrderID = SOD.SalesOrderID
    JOIN Production.Product as PP ON SOD.ProductID = PP.ProductID
)
Select distinct  DateYMD, LastName,  FirstName ,  
, STUFF((
       SELECT ','   t1.OrderContent
         FROM tbl t1
        WHERE t1.DateYMD = t2.DateYMD and t1.LastName = t2.LastName and  t1.FirstName = t2.FirstName 
        ORDER BY t1.OrderContent
          FOR XML PATH('')), 1, LEN(','), '') AS OrderContents
            from tbl t2

CodePudding user response:

You say you only have SQL Server 2016. So you will have to use the FOR XML aggregation method

SELECT 
    CAST(SOH.OrderDate AS DATE) as DateYMD,
    P.LastName,
    P.FirstName,

    STUFF((
        SELECT CONCAT(',', PP.[Name], ' Qty: ', SOD.OrderQty)
        FROM Sales.SalesOrderDetail as SOD
        JOIN Production.Product as PP ON SOD.ProductID = PP.ProductID
        WHERE SOH.SalesOrderID = SOD.SalesOrderID
        FOR XML PATH(''), TYPE
      ).value('text()[1]','nvarchar(max)'),
      1, LEN(','), '') as [OrderContent]

FROM Person.Person as P
    JOIN Sales.Customer SC ON P.BusinessEntityID = SC.PersonID
    OUTER APPLY (
        SELECT TOP 1 subSOH.*
        FROM Sales.SalesOrderHeader as subSOH
        WHERE subSOH.CustomerID = SOH.CustomerID
        ORDER BY subSOH.OrderDate DESC 
    ) SOH;

Note the use of OUTER APPLY to get the top SalesOrderHeader per CustomerID. You could also use ROW_NUMBER() for this.

CodePudding user response:

Thank you very much @Charlieface for demonstrating this solution. I nevertheless made the request a little in my own way, because an additional condition was to make a selection of the very first order for each customer. The final solution to my problem:

SELECT 
    CAST(SOH.OrderDate AS DATE) as DateYMD,
    P.LastName,
    P.FirstName,
STUFF((
        SELECT CONCAT(',', PP.[Name], ' Qty: ', SOD.OrderQty)
        FROM Sales.SalesOrderDetail as SOD
        JOIN Production.Product as PP ON SOD.ProductID = PP.ProductID
        WHERE SOH.SalesOrderID = SOD.SalesOrderID
        FOR XML PATH(''), TYPE
      ).value('text()[1]','nvarchar(max)'),
      1, LEN(','), '') as [OrderContent]
FROM Person.Person as P
    JOIN Sales.Customer SC ON P.BusinessEntityID = SC.PersonID
    JOIN Sales.SalesOrderHeader as SOH ON SC.CustomerID = SOH.CustomerID
    AND SOH.SalesOrderID = (
        SELECT TOP 1 subSOH.SalesOrderID
        FROM Sales.SalesOrderHeader as subSOH
        WHERE subSOH.CustomerID = SOH.CustomerID
        ORDER BY subSOH.OrderDate DESC 
    )
ORDER BY LastName ASC
  • Related