如何将这些键值行转换为完整条目表?
也许我对 SQL 的要求太多了,但我觉得这应该是可能的。我从键值对列表开始,如下所示:
'0:First, 1:Second, 2:Third, 3:Fourth'
等等。我可以通过两步解析轻松地将其拆分,这会得到一个如下表:
EntryNumber PairNumber Item
0 0 0
1 0 First
2 1 1
3 1 Second
等。
现在,在将键值对拆分为一个简单的情况下一对列,这相当容易。我对更高级的情况感兴趣,其中每个条目可能有多个值,例如:
'0:First:Fishing, 1:Second:Camping, 2:Third:Hiking'
等等。
在这种一般情况下,我想找到一种方法来获取 3 列结果表,并以某种方式将其旋转为每个条目一行和每个值部分一列。
所以我想把这个:
EntryNumber PairNumber Item
0 0 0
1 0 First
2 0 Fishing
3 1 1
4 1 Second
5 1 Camping
变成这个:
Entry [1] [2] [3]
0 0 First Fishing
1 1 Second Camping
SQL 处理起来是否太多了,或者有什么办法吗?枢轴(甚至是棘手的动态枢轴)似乎是一个答案,但我不知道如何让它发挥作用。
Maybe I demand too much from SQL but I feel like this should be possible. I start with a list of key-value pairs, like this:
'0:First, 1:Second, 2:Third, 3:Fourth'
etc. I can split this up pretty easily with a two-step parse that gets me a table like:
EntryNumber PairNumber Item
0 0 0
1 0 First
2 1 1
3 1 Second
etc.
Now, in the simple case of splitting the pairs into a pair of columns, it's fairly easy. I'm interested in the more advanced case where I might have multiple values per entry, like:
'0:First:Fishing, 1:Second:Camping, 2:Third:Hiking'
and such.
In that generic case, I'd like to find a way to take my 3-column result table and somehow pivot it to have one row per entry and one column per value-part.
So I want to turn this:
EntryNumber PairNumber Item
0 0 0
1 0 First
2 0 Fishing
3 1 1
4 1 Second
5 1 Camping
Into this:
Entry [1] [2] [3]
0 0 First Fishing
1 1 Second Camping
Is that just too much for SQL to handle, or is there a way? Pivots (even tricky dynamic pivots) seem like an answer, but I can't figure how to get that to work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,在 SQL 中,您无法根据同一查询期间找到的数据动态推断列。
即使使用 Microsoft SQL Server 中的 PIVOT 功能,您在编写查询时也必须知道列,并且必须对它们进行硬编码。
您必须做很多工作才能避免以关系范式形式存储数据。
No, in SQL you can't infer columns dynamically based on the data found during the same query.
Even using the PIVOT feature in Microsoft SQL Server, you must know the columns when you write the query, and you have to hard-code them.
You have to do a lot of work to avoid storing the data in a relational normal form.
好吧,我找到了一种方法来实现我所追求的目标。系好安全带,这会变得颠簸。
因此,基本问题是采用具有两种分隔符的字符串:条目和值。每个条目代表一组值,我想将字符串转换为一个表,每个条目的每个值有一列。我尝试将其设为 UDF,但临时表和动态 SQL 的必要性意味着它必须是存储过程。
这只是基本设置,建立临时表来保存我的中间结果。
这段漂亮的 SQL 来自 SQL Server Central 论坛,并注明出处到“一位大师”。这是一个很棒的小型 10,000 行计数表,非常适合字符串拆分。
好的,这是第一个真正浓密的肉部分。内部选择使用大师的字符串拆分方法沿着项目分隔符(逗号)拆分我的字符串。然后该表被传递到执行相同操作的外部选择,但这次对每行使用值分隔符(冒号)。内部行号 (EntryID) 和分区上的外部行号 (Rank) 是枢轴的关键。 EntryID 显示值属于哪个 Item,Rank 显示值的序号。
最后,动态 SQL 使其成为可能。通过获取不同排名的列表,我们设置了列列表。然后将其写入动态枢轴,动态枢轴将值倾斜并将每个值放入适当的列中,每个值都有一个通用的“Value#”标题。
因此,通过使用格式正确的值字符串调用 EXEC ParseValueList,我们可以将其分解为一个表以实现我们的目的!它适用于简单的键:值对(但可能有点矫枉过正),并且可以扩展到相当数量的列(我认为最多大约 50 个,但这真的很愚蠢。)
无论如何,希望能帮助任何拥有类似的问题。
(是的,它可能也可以用 SQLCLR 之类的东西来完成,但我发现使用纯 SQL 解决问题非常高兴。)
Alright, I found a way to accomplish what I was after. Strap in, this is going to get bumpy.
So the basic problem is to take a string with two kinds of delimiters: entries and values. Each entry represents a set of values, and I wanted to turn the string into a table with one column for each value per entry. I tried to make this a UDF, but the necessity for a temporary table and dynamic SQL meant it had to be a stored procedure.
So that's just basic set up, establishing the temp table to hold my intermediate results.
That beautiful piece of SQL comes from SQL Server Central's Forums and is credited to "a guru." It's a great little 10,000 line tally table perfect for string splitting.
Ok, this is the first really dense meaty part. The inner select is breaking up my string along the item delimiter (the comma), using the guru's string splitting method. Then that table is passed up to the outer select which does the same thing, but this time using the value delimiter (the colon) to each row. The inner RowNumber (EntryID) and the outer RowNumber over Partition (Rank) are key to the pivot. EntryID show which Item the values belong to, and Rank shows the ordinal of the values.
And at last, the dynamic sql that makes it possible. By getting a list of Distinct Ranks, we set up our column list. This is then written into the dynamic pivot which tilts the values over and slots each value into the proper column, each with a generic "Value#" heading.
Thus by calling
EXEC ParseValueList
with a properly formatted string of values, we can break it up into a table to feed into our purposes! It works (but is probably overkill) for simple key:value pairs, and scales up to a fair number of columns (About 50 at most, I think, but that'd be really silly.)Anyway, hope that helps anyone having a similar issue.
(Yeah, it probably could have been done in something like SQLCLR as well, but I find a great joy in solving problems with pure SQL.)
虽然可能不是最佳的,但这里有一个更简洁的解决方案。
Though probably not optimal, here's a more condensed solution.
希望还不算太晚。
您可以使用函数 RANK 来了解每个 PairNumber 中每个 Item 的位置。然后使用枢轴
Hope is not too late.
You can use the function RANK to know the position of each Item per PairNumber. And then use Pivot