如何在没有聚合的情况下转动多个列

时间:2018-05-25 15:33:31

标签: sql sql-server sql-server-2008 sql-server-2012

我使用的是SqlServer,我不得不承认我不是很好... 对于高级用户来说这可能是一个简单的问题(我希望)

我有两个看起来像这样的表

第一个表(ID不是主键)

ID      IdCust   Ref
1       300      123
1       300      124
2       302      345

第二个(ID不是主键)

ID     Ref      Code    Price
1      123      A       10
1      123      Y       15
2      124      A       14
3      345      C       18

在第二个表中,“Ref”列是第一个表中“Ref”的外键

我正在尝试生成以下输出:

The result what i want

[编辑] “Stock”,“Code”和“Price”列可以有x值,所以我不知道,提前...

我尝试了很多像“PIVOT”这样的东西,但它没有给我正确的结果,所以我希望有人能解决我的问题......

2 个答案:

答案 0 :(得分:3)

使用function downloadFile(sUrl) { //iOS devices do not support downloading. We have to inform user about this. if (/(iP)/g.test(navigator.userAgent)) { // alert('Your device does not support files downloading. Please try again in desktop browser.'); window.open(sUrl, '_blank'); return false; } //Creating new link node. var link = document.createElement('a'); link.href = sUrl; link.setAttribute('target','_blank'); if (link.download !== undefined) { //Set HTML5 download attribute. This will prevent file from opening if supported. var fileName = sUrl.substring(sUrl.lastIndexOf('/') + 1, sUrl.length); link.download = fileName; } //Dispatching click event. if (document.createEvent) { var e = document.createEvent('MouseEvents'); e.initEvent('click', true, true); link.dispatchEvent(e); return true; } }功能并执行条件聚合:

row_number()

但是,将使用已知的值,否则您需要使用动态解决方案。

答案 1 :(得分:2)

@ YogeshSharma提供了一个很好的答案。

使用Pivot完成同样的操作; SQL Fiddle Demo

功能上两个答案之间没有区别。然而,Yogesh的解决方案更容易理解,并且表现更好;所以我个人选择这个......我只是因为你在问题中提到了PIVOT而包含了这个答案:

select ft.Id
, ft.IdCust
, ft.Ref
, x.Stock1
, x.Code1
, x.Price1
, x.Stock2
, x.Code2
, x.Price2
from FirstTable ft
left outer join (
  select Ref
  , max([Stock1]) Stock1
  , max([Stock2]) Stock2
  , max([Code1]) Code1
  , max([Code2]) Code2
  , max([Price1]) Price1
  , max([Price2]) Price2
  from
  (
    select Ref
    , Id Stock
    , Code
    , Price
    , ('Stock' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) StockLineNo
    , ('Code' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) CodeLineNo
    , ('Price' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) PriceLineNo
    from SecondTable
  ) st
  pivot (max(Stock) for StockLineNo in ([Stock1],[Stock2])) pvtStock
  pivot (max(Code) for CodeLineNo in ([Code1],[Code2])) pvtCode
  pivot (max(Price) for PriceLineNo in ([Price1],[Price2])) pvtPrice
  Group by Ref
) x
on x.Ref = ft.Ref
order by ft.Ref

与Yogesh的解决方案一样,这只会处理您指定的列数;它不会动态地改变匹配数据的列数。为此,您需要执行动态SQL。然而;如果你需要这样做,你更有可能试图以错误的方式解决问题...所以考虑你的设计/确定你是否真的需要每个结果的额外列而不是额外的行/一些替代方法......

这是基于@ YogeshSharma答案的动态SQL实现:DBFiddle

declare @sql nvarchar(max) = 'select id, IdCust, Ref'
select @sql = @sql + '
        ,max(case when Seq = 1 then stock end) as [Stock' + rowNumVarchar + '] 
        ,max(case when Seq = 1 then code end) as [Code' + rowNumVarchar + ']
        ,max(case when Seq = 1 then price end) as [Price' + rowNumVarchar + ']
'
from 
(
    select distinct cast(row_number() over (partition by ref order by ref) as nvarchar) rowNumVarchar
    from second s
) z
set @sql = @sql + '
    from (select f.*, s.Id Stock, s.Code, s.Price,
                 row_number() over (partition by f.Ref order by s.id) as Seq
         from first f
         inner join second s on s.Ref = f.Ref 
         ) t
    group by id, IdCust, Ref;
'
print @sql --see what the SQL produced is
exec (@sql)

(这里是这个的SQL Fiddle链接;但是尽管SQL有效,它仍无法正常工作