【问题标题】:Pivoting tables in SQL Server in 2019 year and future2019 年和未来 SQL Server 中的数据透视表
【发布时间】:2019-05-24 13:50:19
【问题描述】:

有没有什么方法可以通过优雅的函数在 SQL Server 中实现动态透视表?数据透视表是一种基本实用程序,理论上可以在一行代码中完成。我们只需要定义参数:要透视的列变量(将其值更改为列名)、要聚合的变量、聚合函数和执行透视的表。

我正在寻找 Microsoft 为 2019 年 SQL Server 中的数据透视表提出的语法的替代方案。

我在这里找到了一个实用的替代方案: https://stackoverflow.com/a/45065584/1903793

所有复杂的代码都用存储过程包装。在这个优雅的单行中,我们定义了旋转所需的所有参数。

exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','sum'

但该解决方案的警告是它是一个存储过程,因此它需要一个静态表作为输入,它还输出一个静态表。如果它可能是一种我们可以从中选择的 TVF,那就更好了。

cmets 后更新。 在我开始使用 SQL Server 之前,我什至不知道旋转可能是静态的。需要进行动态旋转。许多其他应用程序在运行中(Excel、Power BI、R)执行数据透视表,而不受列名必须先验已知的约束。在 2005 年可能会遇到一个问题,即实现旋转可以作为带有参数的函数来完成。但是,嘿,我们将走向未来,而我们将在未来几十年为这个基本的表转换实用程序使用复杂的约束语法是荒谬的。

【问题讨论】:

  • 另一种选择,因为您认为语法不可靠,这与实际 需要 动态枢轴完全不同。无论如何,在任何情况下都不可能将这样的东西打包为 TVF,因为 T-SQL 厌恶动态结果集。可以肯定的是,如果您需要输出形状取决于输入的输出,那么唯一可以做到的就是存储过程,即使那样也可能不舒服。 (此外,该语法“只有”14 年的历史,已于 2005 年引入,尽管所涉及的开发人员可能被命名为摩西,也可能不被命名。)
  • TVF 会更好,但它们不支持动态 SQL。
  • 老实说,我不记得 PIVOT 的语法了,但那是因为我只使用交叉表,因为它们的性能更好,而且它们的功能更灵活。
  • 不清楚你在寻找什么样的答案。显然,如果您提供赏金,当前的人不会为您做这件事,但实际上,您想从这个问题中得到什么?验证你的意见?微软的承诺?对于“是否有一种简单的方法可以在 T-SQL 中进行动态透视”的简短而准确的回答是“否”。还有其他问题可以解决问题本身,并且您已经链接到其中之一。还有什么?
  • @PrzemyslawRemin,你已经得到了这个问题的答案。动态枢轴的唯一解决方案或“解决方法”是执行使用动态 SQL 的存储过程。没有替代。 CLR 函数将无济于事,因为它还必须先验定义其输出列 - SQL 中的任何“函数”,其结果可能通过管道传递到进一步的查询中,都必须具有静态表结构。

标签: sql sql-server pivot pivot-table


【解决方案1】:

但需要注意的是,它是一个存储过程,因此它需要一个静态表作为输入,它还输出一个静态表。

我不明白这一点。表名是参数之一,因此不需要“静态表”。

更重要的是,存储过程不能写成(合理的)用户定义函数,因为它需要动态SQL。并且用户函数不支持动态 SQL。

您还需要意识到FROM 子句中的任何内容都要求在查询的编译阶段知道列和列类型。这排除了使用字符串来指定列名,因为字符串可以是参数。

【讨论】:

  • 您要责备哪个标准委员会?据我所知,PIVOT 不是任何版本的 ANSI SQL 的一部分,我不会将那些想出新事物以放入 T-SQL 的人称为委员会(如果他们是,他们负责的不是标准……)
  • @JeroenMostert 。 . .我想我有一个简写,如果 Oracle 和 SQL Server 都支持特定功能,那么它必须是标准的。在这种情况下失败了。谢谢你让我诚实。
【解决方案2】:

Excel 实际上并没有完全执行动态透视 - 您仍然必须使用 GUI 指定透视列的顺序或列名的别名来优化最终呈现(尽管在某些有限的情况下这并不重要) .

您也(据我记得)不能在 Excel 中指定其标题在源数据中根本不存在的列 - 在某些情况下,您必须在源中包含虚拟行,只是为了强制特定列存在于枢​​轴输出中(尽管此类列中的值都将为零或空,但在最终报告中明确说明和/或保持枢轴的视觉结构通常很重要)。

显然,SQL 要求所有这些都在代码本身中预先完成。

我同意 SQL 语法是坑,但老实说,除非列顺序无关紧要,否则列名不需要别名,并且不需要存在特定列(在绝大多数情况下,动态枢轴实际上是有用的),那么我看不出还有什么办法可以解决这个问题。

黑客使用存储过程调用动态 SQL,程序员可以灵活地确定行为的所有方面并将其与特定情况的要求相匹配,这可能是可以实现的最佳平衡。

【讨论】:

    【解决方案3】:

    SQL Server 是一个关系数据库管理系统。关系的概念是其设计的基础。所有关系数据库管理系统都是在假设数据库的模式是稳定的情况下设计的。换句话说,所有 RDBMS 都假定表列表及其列是静态的。当数据以这种方式结构化时,它们旨在高效工作。

    您似乎对一个并非为它设计的工具抱有一些期望。

    我没有使用非关系 DBMS 的经验。现在有很多,其中一些可能比 RDBMS 更适合您的任务。

    使用 RDBMS 时,通常会分离数据及其对最终用户的表示。

    RDBMS 的任务是在驻留在服务器上的大型数据库中有效地查找和聚合所需的数据子集,并将小型结果集返回给客户端。客户端报告工具的任务是获取此结果数据集并以最终用户想要的方式对其进行格式化。例如,在金额前显示美元符号,将值四舍五入到必要的精度,以带有小计的交叉表的形式打印出值等。透视是一种普遍的广泛需求,有很多报告工具可以以您喜欢的任何方式格式化数据的小子集,但这些工具不是数据库管理系统。


    是的,一般而言,RDBMS 尤其是 SQL Server 具有一些处理动态数据库模式的功能,但它们通常笨拙且丑陋,例如动态 SQL 和 PIVOT 语法。它们不是为此而设计的。

    【讨论】:

    • 我同意这就是现在的概念(或缺乏概念),除非微软团队最终提出了一个简单的旋转功能,我相信他们最终会这样做。或者您是说不允许微软改进该功能?您可能会在 1990 年代说,这就是我们必须在 DOS 中编写命令的操作系统概念。幸运的是,我们不必这样做。
    • @PrzemyslawRemin,我不认为操作系统 GUI 是一个很好的类比。不知何故,即使有一个可调节的扳手,人们仍会继续携带一套笨重、不灵活的固定尺寸扳手。你可以用编译成可执行机器代码的语言和逐行解释的语言编写程序。针对不同任务的不同工具。当预先知道表中列的类型和数量时,结构化、规范化数据的概念是 SQL Server 实现的基础。可能还有其他数据库/工具更适合您的任务 - 使用它们。
    • 顺便说一句,Microsoft 在最新版本的 SQL Server 中添加了对 R 和其他非关系工具/语言的一些支持。我不知道细节,但你可能会发现它很有用。
    • @PrzemyslawRemin,“你是说不允许微软改进该功能吗?” MS 可以做他们想做的事,有时他们甚至会倾听他们当前和未来客户的意见,并在他们的产品中添加请求的功能。我怀疑 MS 向 SQL Server 添加对动态数据透视的支持在技术上是否容易。我认为这真的很难。在我看来,这个功能相当小众。所以,我认为微软在可预见的未来实施它的可能性非常低。
    • 短语 SQL pivot 在 0.56 秒内返回 7,010,000 个结果。至于利基的衡量标准。
    【解决方案4】:

    您可以使用动态 SQL 查询并在单个查询中执行您想要的结果。但首先,我们将在不同变量中准备查询的不同组件,然后将所有这些组件组合在一起以根据我们想要的输出结果进行单个查询。

    您将在 @query 之类的 varchar 类型的变量中声明您的查询。通过在查询中添加不同的组件,您将创建任何不依赖于单个表但对传入的任何表名或参数执行类似操作的动态查询。

    构建查询后,您可以使用execexec sp_executesql 执行查询并获得所需的结果。

    【讨论】:

    • 你有什么建议?在我的问题中链接到的答案中构建一个动态查询?该查询至少有 30 行代码。我的问题是关于如何搜索单线。请查看 R 中的语法有多简单。在 R 中查看不同的答案 stackoverflow.com/questions/18622854/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    相关资源
    最近更新 更多