简体   繁体   中英

How to generate column based on order id in sql

I have two tables: customerTable and orderTable that are shown below. I need to generate order column dynamically.

CustomerTable

custId CustName
01     Suresh
02     Ramesh

OrderTable

custId  OrderId 
01      011
01      012

need output as like :

custId Order1 Order2
01     011    012

Here if order is multiple times for each customer then columns will be added dynamically.

If custId = 01 has 011,012,013,014...... has many order then table will be like

custId order1  order2 order3 order4 order5 order6 ...... many oder N columns 
01     011       012   013   014    015    06     ....... 0N..   

What you are looking for is called pivoting. See the documentation .

A simple example taken from the link above:

USE AdventureWorks2008R2;
GO
SELECT
    DaysToManufacture,
    AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;

Results in:

DaysToManufacture | AverageCost
----------------------------------------
0                 | 5.0885
1                 | 223.88
2                 | 359.1082
4                 | 949.4105

These are rows in the source table grouped, no pivoting done yet. By pivoting, you turn the values of the rows in column #1 into columns, and the values of the rows in column #2 get 'rotated' and appear as one row. The SQL to do that is the following:

-- Pivot table with one row and five columns
SELECT
    'AverageCost' AS Cost_Sorted_By_Production_Days, 
    [0],
    [1],
    [2],
    [3],
    [4]
FROM
(
    SELECT
        DaysToManufacture,
        StandardCost 
    FROM
        Production.Product
) AS SourceTable
PIVOT
(
    AVG(StandardCost)
    FOR DaysToManufacture IN
    (
        [0],
        [1],
        [2],
        [3],
        [4]
    )
) AS PivotTable;

This results in output such as:

Cost_Sorted_By_Production_Days | 0      | 1      | 2        | 3    | 4
-----------------------------------------------------------------------------
AverageCost                    | 5.0885 | 223.88 | 359.1082 | NULL | 949.4105

Do this dynamically like this:

declare @sql as nvarchar(max)
declare @cols as nvarchar(max)

set @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.OrderId)
            FROM OrderTable c
            order by 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @sql = STUFF((SELECT ',' + QUOTENAME(OrderId) + ' as Order' + convert(varchar,row_number() over (order by OrderId))
            from (
                select distinct OrderId 
                FROM OrderTable
            ) t
            order by 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @sql = 'SELECT custId, ' + @sql + ' from 
            (
                select *
                from OrderTable
           ) x
            pivot 
            (
                 max(OrderId)
                for OrderId in (' + @cols + ')
            ) p '
exec(@sql)

Produces:

在此处输入图片说明

To be noted here is that, it works correctly for one custId as the columns are aligned based on the the OrderId in the pivoted result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM