【问题标题】:How to pivot by two columns into predefined table?如何将两列旋转到预定义的表中?
【发布时间】:2018-09-19 20:18:24
【问题描述】:

我见过this questionthisthis,但这些不是我想要的。

请不要关闭我的问题,因为它不是重复的。这对我来说真的很重要。

我已经成功地旋转了一个表格,但这不是我们想要的结果:

想要的结果如下所示:

我的示例数据是(这只是一个示例,OperatorXOC 列应该是 50 次):

DECLARE @OperatorPrice TABLE (ID INT NOT NULL, OperatorId INT NULL, Price 
NUMERIC(18,3) NULL, FName VARCHAR(50) NULL)

INSERT INTO @OperatorPrice (
ID, OperatorId, Price, FName
)
VALUES
  (226, 996, 22954,'Operator1')
, (266, 1016, 79011.2,   'Operator3')
, (112, 1029, 14869,     'Operator4')
, (93,   1031, 10568.96, 'Operator5')


DECLARE @TR TABLE 
(
 ID INT NULL , 
    Operator1  DECIMAL(18,3) NULL, OC1  DECIMAL(18,3) NULL, Operator2  DECIMAL(18,3) NULL, 
    OC2  DECIMAL(18,3) NULL, Operator3  DECIMAL(18,3) NULL, OC3  DECIMAL(18,3) NULL, 
    Operator4  DECIMAL(18,3) NULL, OC4  DECIMAL(18,3) NULL, Operator5  DECIMAL(18,3) NULL, 
    OC5  DECIMAL(18,3) NULL
)

示例代码:

INSERT @TR
(ID , 
Operator1, OC1, Operator2, OC2,  Operator3, OC3,  Operator4, OC4,  
Operator5, OC5)
SELECT ID , 
    Operator1, OC1, Operator2, OC2,  Operator3, OC3,  Operator4, OC4,  
Operator5, OC5
FROM 
(SELECT Price, id, FName 
FROM @OperatorPrice) AS SourceTable 
PIVOT 
( 
   sum(Price)
   FOR FName IN (Operator1, OC1, Operator2, OC2,  Operator3, OC3,  
   Operator4, OC4,  Operator5, OC5) 
) AS PivotTable

SELECT * FROM @TR

如何将数据插入OC 列?

【问题讨论】:

  • 这是你昨天问的同一个问题。它仍然不清楚你想要什么。 @ 987654326@ 您将使用插入语句插入这些列...奇怪...就像您在此处发布的问题一样。但我怀疑这不是你要问的。发布 ddl 和示例数据的工作很棒,但这个问题毫无意义。
  • @Sean Lange 不一样。请仔细阅读我的问题,只是不要关闭我的问题。现在我可以插入数据,但数据应该由两列组成!请不要关闭我的帖子。
  • 您会注意到我没有对此投反对票或将其标记为关闭。事实上,您在发布数据和表结构方面做得很好。我只是不明白这个问题。
  • 我看到数据进入了其他列,但为什么是 Operator3 OC3?字符串运算符总是在数据中吗?这就是这里真正令人困惑的地方。有没有更好的方法来确定运营商的数量?我认为条件聚合在这里会容易得多,但我们需要一些方法来知道哪个运算符号是什么。
  • @StepUp 您可以使用条件聚合非常轻松地做到这一点。给出一个很好的理由说明您引用的第三个问题对您没有帮助:stackoverflow.com/a/44030551/1507566 只需稍加思考即可将其应用于两列而不是一列。

标签: sql-server tsql pivot


【解决方案1】:

也许是这样的。

在您的别名 SOURCETABLE 中,我们只需为带有 NULL 值的 ID 添加一个 UNION ALL 的可能组合。在这种情况下,MIN(ID) 和值 1 - 50

一定要这样做

1) 使用列 Operator1,OC1,..,Operator50,OC50 定义 @TR OC# 可以是 INT

2) 在FOR Item IN(Operator1,OC1,..,Operator50,OC50)

示例 -- 编辑更正以允许 >9 个运算符

INSERT @TR
SELECT *
FROM  (
        Select A.ID
              ,B.*
         From  @OperatorPrice A
         Cross Apply ( values (FName,Price)
                             ,('OC'+replace(FName,'Operator',''),OperatorID)
                     ) B (Item,Value)
        Union All
        Select ID=(select min(ID) From @OperatorPrice)
              ,B.*
         From ( Select Top 50 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1 ) A
         Cross Apply ( values (concat('Operator',N),NULL)
                             ,(concat('OC',N),NULL)
                     ) B (Item,Value)
       ) AS SourceTable 
PIVOT  ( sum(Value) FOR Item IN (Operator1, OC1, Operator2, OC2,  Operator3, OC3, Operator4, OC4,  Operator5, OC5) ) AS PivotTable

Select * from  @TR

返回——注意 Operator2

【讨论】:

  • 非常感谢!它完美地工作!请您澄清一下Over (Order By (Select NULL)) From master 是什么意思?提前致谢!
  • @StepUp 在这里,我们通过 row_number() 创建一个临时计数或数字表。在这种情况下,目标是获得 1 到 50 之间的数字范围(因此是前 50 名)。 Row_Number() 需要 Order By。我使用 select null (一个常量)有两个原因。 1)它更快,因为没有什么要排序,优化器将其视为一个常量 2)而不是 master... 您可以使用任何行数足够的表,并且 order by 不链接到特定字段。
  • @StepUp 如果您还没有这样做。运行各个语句。从 Select to 50 N=-... 开始,然后运行 ​​UNION ALL 后面的 Select
  • 您能看到这个问题吗? stackoverflow.com/questions/52461516/…
【解决方案2】:

使用您的示例表和数据,通过条件聚合很容易做到这一点。尽管您如何确定哪个操作员号码是哪个,但并不是很清楚。希望您有比从值中解析数字更好的方法,但谁知道呢。

select op.ID
    , Operator1 = max(case when convert(int, replace(FName, 'Operator', '')) = 1 then Price end)
    , OC1 = max(case when convert(int, replace(FName, 'Operator', '')) = 1 then OperatorID end)
    , Operator2 = max(case when convert(int, replace(FName, 'Operator', '')) = 2 then Price end)
    , OC2 = max(case when convert(int, replace(FName, 'Operator', '')) = 2 then OperatorID end)
    , Operator3 = max(case when convert(int, replace(FName, 'Operator', '')) = 3 then Price end)
    , OC3 = max(case when convert(int, replace(FName, 'Operator', '')) = 3 then OperatorID end)
    , Operator4 = max(case when convert(int, replace(FName, 'Operator', '')) = 4 then Price end)
    , OC4 = max(case when convert(int, replace(FName, 'Operator', '')) = 4 then OperatorID end)
    , Operator5 = max(case when convert(int, replace(FName, 'Operator', '')) = 5 then Price end)
    , OC5 = max(case when convert(int, replace(FName, 'Operator', '')) = 5 then OperatorID end)
from @OperatorPrice op
cross apply
(
    values
    (1)
    ,(2)
    ,(3)
    ,(4)
)x(N)
group by op.ID

【讨论】:

    猜你喜欢
    • 2011-03-08
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多