Показывать заказанные статьи на пользователя - PullRequest
0 голосов
/ 14 мая 2019

У меня есть следующее:

customerID | OrderID | OrderPosition | Articlenumber|
-----------+---------+---------------+--------------+
101        | 1       | 1             | 123          |
101        | 1       | 2             | 799          |
102        | 2       | 1             | 111          |
103        | 3       | 1             | 456          |
101        | 4       | 1             | 789          |
103        | 5       | 1             | 444          |
103        | 5       | 2             | 999          |
101        | 6       | 1             | 555          |
101        | 6       | 2             | 777          |
101        | 6       | 3             | 222          |

, и я хочу следующее (в сумме не более 4 статей (упорядоченных по orderID (сначала выше) и OrderPosition (сначала снизу)) для customerID):

customerID |articelnumber 1|articelnumber 2|articelnumber 3|articelnumber 4|
-------+-------------------+---------------+---------------+---------------+
101        |555            |777            |222            | 789           |
102        |111            |NULL           |NULL           |NULL           |
103        |444            |999            |456            |NULL           |

Попробовал вот так, но это не работает правильно:

select *
from 
(
select customerid, OrderID , OrderPosition, Articlenumber FROM table
) src
pivot
(
  avg (Articlenumber)
  for OrderPosition in ([articelnumber 1], [articelnumber 2], [articelnumber 3], [articelnumber 4])
) piv

Ответы [ 3 ]

1 голос
/ 14 мая 2019

Мне потребовалось некоторое время, чтобы получить те же результаты, что и ожидаемый результат, но мне все-таки удалось все исправить:

if exists (select 1 from sysobjects where name = 'TempTable')
drop table TempTable;

if exists (select 1 from sysobjects where name = 'TempTable2')
drop table TempTable2;

declare @cols   nvarchar(max)
,       @cols2  nvarchar(max)
,       @sql  nvarchar(max)
,       @loop   int;

create table TempTable (id int primary key identity, CustomerID int, OrderID int, OrderPosition int, ArticleNumber int)

insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,1,1,123)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,1,2,799)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (102,2,1,111)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,3,1,456)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,4,1,789)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,5,1,444)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,5,2,999)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,1,555)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,2,777)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,3,222);

create table TempTable2 (CustomerID int, OrderID int, OrderPosition int, ArticleNumber int, ArticleDesc varchar(100))

select @loop = min(id) from TempTable
while @loop is not null

begin
    set @sql    = ' insert into TempTable2 (CustomerID, OrderID, OrderPosition, ArticleNumber, ArticleDesc)
                    select top 4 CustomerID, OrderID, OrderPosition, ArticleNumber, ''ArticleNumber ''+cast(rank() over (order by orderID desc, OrderPosition)as varchar)
                    from    TempTable where CustomerID = '+cast((select CustomerID from TempTable where id = @loop) as varchar)+
                    'order by orderID desc, OrderPosition'
    exec (@sql)
    select @loop = min(id) from TempTable where id > @loop
end

select
    CustomerID
,   sum(isnull([ArticleNumber 1],0))    [ArticleNumber 1]
,   sum(isnull([ArticleNumber 2],0))    [ArticleNumber 2]
,   sum(isnull([ArticleNumber 3],0))    [ArticleNumber 3]
,   sum(isnull([ArticleNumber 4],0))    [ArticleNumber 4]
from
(
select
CustomerID, OrderID, OrderPosition, ArticleDesc, ArticleNumber
from    TempTable2
group by CustomerID, OrderID, OrderPosition, ArticleDesc, ArticleNumber
)   d
pivot
(sum(ArticleNumber) for ArticleDesc in ([ArticleNumber 1],[ArticleNumber 2],[ArticleNumber 3],[ArticleNumber 4])
)   p
group by CustomerID

Мой ответ может быть не самым лучшим, поскольку гениальные парни ответили выше, но я все равно получаю те же результаты ...

Results

0 голосов
/ 14 мая 2019

Если вам нужно только четыре столбца и быстрый вывод такой же, как указано выше, вы всегда можете просто использовать ROW_NUMBER, CTE и несколько объединений:

;with TopFour
as
(
    SELECT *,
        ROW_NUMBER() OVER(PARTITION BY [customerID] ORDER BY orderID DESC, OrderPosition ASC) as [TheOrder]
    FROM [table]
)
SELECT
    a.[customerID],
    a.[Articlenumber] as [articlenumber 1],
    b.[Articlenumber] as [articlenumber 2],
    c.[Articlenumber] as [articlenumber 3],
    d.[Articlenumber] as [articlenumber 4]
FROM 
    TopFour a
LEFT JOIN 
    TopFour b
ON 
    a.customerID = b.customerID
AND 
    b.TheOrder = 2
LEFT JOIN
    TopFour c
ON 
    a.customerID = c.customerID
AND 
    c.TheOrder = 3
LEFT JOIN 
    TopFour d
ON 
    a.customerID = d.customerID
AND 
    d.TheOrder = 4
WHERE 
    a.TheOrder = 1
0 голосов
/ 14 мая 2019

Модифицированные данные образца для удовлетворения ваших требований

IF OBJECT_ID('tempdb..#TEMP ')IS NOT NULL
DROP TABLE  #TEMP 
;WITH CTE(customerID , OrderID , OrderPosition , Articlenumber)
AS
(
SELECT 101,  1 , 1 , 123 UNION ALL         
SELECT 101,  1 , 2 , 799 UNION ALL         
SELECT 102,  2 , 1 , 111 UNION ALL         
SELECT 103,  3 , 1 , 456 UNION ALL         
SELECT 101,  4 , 1 , 789 UNION ALL         
SELECT 103,  5 , 1 , 444 UNION ALL         
SELECT 103,  5 , 2 , 999 UNION ALL         
SELECT 101,  6 , 1 , 555 UNION ALL         
SELECT 101,  6 , 2 , 777 UNION ALL         
SELECT 101,  6 , 3 , 222          
)
SELECT * , SUM(ArticleNumber)OVER(PARTITION BY customerID  ORDER BY customerID ) AS SumOfArticlePerCustomer
INTO #TEMP 
FROM
(
SELECT * ,
    ROW_NUMBER()OVER(PARTITION BY customerID ORDER BY OrderID DESC  ) RNk,
    'ArticleNumber_'+CAST(ROW_NUMBER()OVER(PARTITION BY customerID ORDER BY OrderID DESC ) AS VARCHAR(10))  AS ArticleNumberData
FROM CTE
)DT
WHERE RNk <= 4

SELECT * FROM #TEMP

Динамический Sql, который используется для динамической генерации столбца и достижения ожидаемого результата

DECLARE @Sql nvarchar(max),
        @DynamicColumn nvarchar(max),
        @MaxDynamicColumn nvarchar(max)

SELECT @DynamicColumn = STUFF((SELECT DISTINCT', '+QUOTENAME(ArticleNumberData )
FROM #TEMP  FOR XML PATH ('')),1,1,'') 

SELECT @MaxDynamicColumn = STUFF((SELECT DISTINCT', '+'MAX('+QUOTENAME(ArticleNumberData )+') AS '+QUOTENAME(ArticleNumberData )+CHAR(13)+CHAR(10)
FROM #TEMP FOR XML PATH (''),TYPE).value('text()[1]','nvarchar(max)'),1,1,N'')

SET @Sql='SELECT  CustomerID,'+ @MaxDynamicColumn+',SumOfArticlePerCustomer 
            FROM
            (
            SELECT *
            FROM #TEMP 
            )AS src
            PIVOT 
            (
            MAX(Articlenumber) FOR [ArticleNumberData] IN ('+@DynamicColumn+')
            ) AS Pvt
            GROUP BY customerID,SumOfArticlePerCustomer
            ORDER BY  CustomerID'
EXEC (@Sql)
PRINT @Sql
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...