[英]“Pivoting” non-aggregate data in SQL Server
this will be the first question I've posted here so pardon any unintended lapses in board etiquette. 这将是我在这里发布的第一个问题,因此请原谅任何无意识的董事会礼仪失误。
In my current project, I've taken a large, non-normalized table and broken it into four separate, normalized tables. 在我当前的项目中,我采用了一个非规范化的大型表,并将其分解为四个独立的规范化表。 My ultimate goal that I'm reaching out to this board for is to create a view which mimics the non-normalized table for backwards compatibility. 我接触到这个板的最终目标是创建一个模拟非规范化表以便向后兼容的视图。
To provide a simplified snapshot of my scenario, the crux of what I'm trying to do lies in two tables: 为了提供我的场景的简化快照,我正在尝试做的关键在于两个表:
ASSOC_ROLE ASSOCIATE
---------- ----------
assoc_id (fk) assoc_id (pk)
role_id (fk) last_name
org_nbr (fk)
So if I issue the following query... 所以,如果我发出以下查询......
SELECT Assoc_Role.org_nbr, Assoc_Role.assoc_id, Associate.last_name, Assoc_Role.role_id
FROM Assoc_Role INNER JOIN
Associate ON Assoc_Role.assoc_id = Associate.assoc_id
WHERE Assoc_Role.org_nbr = '1AA'
...I get the following result set ...我得到以下结果集
org_nbr assoc_id last_name role_id
------- -------- --------- -------
1AA 1447 Cooper 1
1AA 1448 Collins 3
1AA 1448 Collins 4
1AA 1448 Collins 5
1AA 1449 Lynch 6
Ultimately, the view I would like to construct would look something like this: 最终,我想构建的视图看起来像这样:
org_nbr role1_ID role1_name role2_ID role2_name role3_ID role3_name role4_ID role4_name role5_ID role5_name role6_ID role6_name
------- -------- ---------- -------- ---------- -------- ---------- -------- ---------- -------- ---------- -------- ----------
1AA 1447 Cooper NULL NULL 1448 Collins 1448 Collins 1448 Collins 1449 Lynch
My initial thought was to try to use the PIVOT command, but my understanding is that PIVOT requires some kind of aggregation, and that doesn't fit my scenario. 我最初的想法是尝试使用PIVOT命令,但我的理解是PIVOT需要某种聚合,这不适合我的场景。 I've also played around with the CASE command in the SELECT clause, but it doesn't flatten my result set down to one record. 我也在SELECT子句中使用了CASE命令,但它并没有将我的结果集压缩到一个记录。
Hopefully someone can shed some light on how I can accomplish this. 希望有人可以阐明如何实现这一目标。 Let me know if anyone needs more info. 如果有人需要更多信息,请告诉我。 Thanks! 谢谢!
Scot 苏格兰人
To get the basic numbered-role data, we might start with 要获得基本的编号角色数据,我们可以从中开始
SELECT
org_nbr
, r1.assoc_id role1_ID
, r1.last_name role1_name
, r2.assoc_id role2_ID
, r2.last_name role2_name
, r3.assoc_id role3_ID
, r3.last_name role3_name
, r4.assoc_id role4_ID
, r4.last_name role4_name
, r5.assoc_id role5_ID
, r5.last_name role5_name
, r6.assoc_id role6_ID
, r6.last_name role6_name
FROM
ASSOC_ROLE ar
LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id
LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id
LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id
LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id
LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id
LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id
BUT this will give us, for each org_nbr
, a separate row for each role_id
that has data! 但是 ,对于每个org_nbr
,这将为每个具有数据的role_id
一个单独的行! Which is not what we want - so we need to GROUP BY org_nbr
. 这不是我们想要的 - 所以我们需要GROUP BY org_nbr
。 But then we need to either GROUP BY
or aggregate over every column in the SELECT
list! 但是,我们需要GROUP BY
或聚合SELECT
列表中的每一列! The trick then is to come up with an aggregate function that will placate SQL Server and give us the results we want. 接下来的技巧是提出一个聚合函数,它将安抚SQL Server 并为我们提供我们想要的结果。 In this case, MIN
will do the job: 在这种情况下, MIN
将完成这项工作:
SELECT
org_nbr
, MIN(r1.assoc_id) role1_ID
, MIN(r1.last_name) role1_name
, MIN(r2.assoc_id) role2_ID
, MIN(r2.last_name) role2_name
, MIN(r3.assoc_id) role3_ID
, MIN(r3.last_name) role3_name
, MIN(r4.assoc_id) role4_ID
, MIN(r4.last_name) role4_name
, MIN(r5.assoc_id) role5_ID
, MIN(r5.last_name) role5_name
, MIN(r6.assoc_id) role6_ID
, MIN(r6.last_name) role6_name
FROM
ASSOC_ROLE ar
LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id
LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id
LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id
LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id
LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id
LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id
GROUP BY
org_nbr
Output: 输出:
org_nbr role1_ID role1_name role2_ID role2_name role3_ID role3_name role4_ID role4_name role5_ID role5_name role6_ID role6_name
---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ----------
1AA 1447 Cooper NULL NULL 1448 Collins 1448 Collins 1448 Collins 1449 Lynch
Warning: Null value is eliminated by an aggregate or other SET operation.
Of course this will fall short should the maximum role_id
increase... 当然,如果最大的role_id
增加,这将role_id
......
If you can, I would highly recommend doing this type of pivoting in regular code (c#, vb, whatever). 如果可以,我强烈建议在常规代码(c#,vb,无论如何)中进行这种类型的旋转。
PIVOTing in SQL server has a lot of drawbacks. SQL服务器中的PIVOTing有很多缺点。 First, anything over 7 or 8 items is going to massively increase the amount of time your queries take. 首先,超过7或8项的任何内容都会大大增加查询所需的时间。 Second, it requires you to either do dynamic sql OR to know all the potential id's ahead of time. 其次,它要求你做动态sql或提前知道所有潜在的id。 Third, it will be difficult to maintain. 第三,难以维持。
The same problems exist in AakashM's answer. AakashM的回答也存在同样的问题。
We've tried a lot of different ways to make this work in a pure SQL setting. 我们已经尝试了很多不同的方法来使这个工作在纯SQL设置中。 For small data sets with very limited pivot's it will work just fine. 对于枢轴非常有限的小型数据集,它可以正常工作。 However, the number of Role Id's you already have go beyond it. 但是,您已经拥有的角色ID数量超出了它。
Instead, just grab the data and in your favorite language create the table you need. 相反,只需抓住数据并用您喜欢的语言创建您需要的表格。 At that point either put the data into a different sql table or send it along to where ever it needs to go. 此时要么将数据放入不同的sql表中,要么将其发送到需要的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.