如何在 SQL select 语句中动态创建列

2023-12-09

我有3张桌子。团队,选项,选项团队。
团队拥有 TeamId 和 Name
Option保存OptionId、OptionGroup
OptionTeam持有TeamId、OptionId、OptionGroup

select a.TeamId, a.Name
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=4) as Option1,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=5) as Option2,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=6) as Option3,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=11) as Option4
from Team a 

我想要获取团队列表,以及指示每个组有多少个选项连接到每个团队的额外列。这是通过上面的查询完成的,但我想用表 Option 中的 OptionGroup 值替换 4,5,6,11。
它必须是动态的,因为将来可能会有一个新的OptionGroup,并且我希望存储过程能够处理它。

样本数据:

Team  
TeamId  
1  
2  
3  

Option

OptionId | OptionGroup  
11 | 4  
12 | 5  
13 | 4  
14 | 4  
15 | 5  

选项团队

TeamId | OptionId | OptionGroup  
1 | 11 | 4  
1 | 13 | 4  
2 | 12 | 5  
2 | 14 | 4  
3 | 15 | 5  

我想要得到的列表是

TeamId | Group4 (OptionGroup=4) | Group5 (OptionGroup=5)  
1 | 2 | 0  
2 | 1 | 1  
3 | 0 | 1  

您需要一个动态枢轴才能做到这一点。这是存储过程:

CREATE PROC [dbo].[pivotsp]
      @query    AS NVARCHAR(MAX),                   -- The query, can also be the name of a table/view.
      @on_rows  AS NVARCHAR(MAX),                   -- The columns that will be regular rows.
      @on_cols  AS NVARCHAR(MAX),                   -- The columns that are to be pivoted.
      @agg_func AS NVARCHAR(257) = N'SUM',          -- Aggregate function.
      @agg_col  AS NVARCHAR(MAX),                   -- Column to aggregate.
      @output   AS NVARCHAR(257) = N'',             -- Table for results
      @debug    AS bit = 0                          -- 1 for debugging
    AS

    -- Example usage:
    --    exec pivotsp
    --          'select * from vsaleshistory',
    --          'market,marketid,family,familyid,Forecaster,Forecasterid,product,productid',
    --          'month',
    --          'sum',
    --          'ku',
    --          '##sales'

    -- Input validation
    IF @query IS NULL OR @on_rows IS NULL OR @on_cols IS NULL
       OR @agg_func IS NULL OR @agg_col IS NULL
    BEGIN
      RAISERROR('Invalid input parameters.', 16, 1);
      RETURN;
    END

    -- Additional input validation goes here (SQL Injection attempts, etc.)

    BEGIN TRY
      DECLARE
        @sql     AS NVARCHAR(MAX),
        @cols    AS NVARCHAR(MAX),
        @newline AS NVARCHAR(2);

      SET @newline = NCHAR(13) + NCHAR(10);

      -- If input is a valid table or view
      -- construct a SELECT statement against it
      IF COALESCE(OBJECT_ID(@query, N'U'),
                  OBJECT_ID(@query, N'V')) IS NOT NULL
        SET @query = N'SELECT * FROM ' + @query;

      -- Make the query a derived table
      SET @query = N'(' + @query + N') AS Query';

      -- Handle * input in @agg_col
      IF @agg_col = N'*'
        SET @agg_col = N'1';

      -- Construct column list
      SET @sql =
          N'SET @result = '                                    + @newline +
          N'  STUFF('                                          + @newline +
          N'    (SELECT N'','' +  quotename( '
                       + 'CAST(pivot_col AS sysname)' +
                       + ')  AS [text()]'                          + @newline +
          N'     FROM (SELECT DISTINCT('
                       + @on_cols + N') AS pivot_col'              + @newline +
          N'           FROM' + @query + N') AS DistinctCols'   + @newline +
          N'     ORDER BY pivot_col'                           + @newline +
          N'     FOR XML PATH(''''))'                          + @newline +
          N'    ,1, 1, N'''');'

      IF @debug = 1
         PRINT @sql

      EXEC sp_executesql
        @stmt   = @sql,
        @params = N'@result AS NVARCHAR(MAX) OUTPUT',
        @result = @cols OUTPUT;

      IF @debug = 1
         PRINT @cols

      -- Create the PIVOT query
      IF @output = N''
          begin
            SET @sql =
                N'SELECT *'                                          + @newline +
                N'FROM (SELECT '
                              + @on_rows
                              + N', ' + @on_cols + N' AS pivot_col'
                              + N', ' + @agg_col + N' AS agg_col'        + @newline +
                N'      FROM ' + @query + N')' +
                              + N' AS PivotInput'                        + @newline +
                N'  PIVOT(' + @agg_func + N'(agg_col)'               + @newline +
                N'    FOR pivot_col IN(' + @cols + N')) AS PivotOutput;'
          end
      ELSE
          begin
            set @sql = 'IF  EXISTS (SELECT * FROM tempdb.sys.objects WHERE  ' +
                'name = ''' + @output + ''' AND type = N''U'') DROP TABLE tempdb.' + @output
            EXEC sp_executesql @sql;

            SET @sql =
                N'SELECT * INTO ' + @output                          + @newline +
                N'FROM (SELECT '
                              + @on_rows
                              + N', ' + @on_cols + N' AS pivot_col'
                              + N', ' + @agg_col + N' AS agg_col'        + @newline +
                N'      FROM ' + @query + N')' +
                              + N' AS PivotInput'                        + @newline +
                N'  PIVOT(' + @agg_func + N'(agg_col)'               + @newline +
                N'    FOR pivot_col IN(' + @cols + N')) AS PivotOutput;'
          end

        IF @debug = 1
           PRINT @sql

        EXEC sp_executesql @sql;
    END TRY
    BEGIN CATCH
      DECLARE
        @error_message  AS NVARCHAR(2047),
        @error_severity AS INT,
        @error_state    AS INT;

      SET @error_message  = ERROR_MESSAGE();
      SET @error_severity = ERROR_SEVERITY();
      SET @error_state    = ERROR_STATE();

      RAISERROR(@error_message, @error_severity, @error_state);

      RETURN;
    END CATCH

这样,就可以轻松地在可变数量的列上进行旋转:

EXEC pivotsp
        'SELECT TeamID, OptionGroup, OptionID AS Options FROM OptionTeam',
        'Teamid',        -- Row headers
        'optiongroup',   -- item to aggregate
        'count',         -- aggregation function
        'optiongroup',   -- Column header
        '##temp'         -- output table name
    SELECT * FROM ##temp

Results:

   Teamid   4   5
    1   2   0
    2   1   1
    3   0   1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 SQL select 语句中动态创建列 的相关文章

随机推荐

  • 如何检查用户是否登录

    我创建了一个登录页面 用户必须提供用户名和密码才能访问某些特定资源 他们可以在其中上传图像 或者只是编辑一些有关自己的描述 我的 web config 文件如下所示
  • php:获取ip地址

    我想获取访客的IP地址 你能告诉我什么元素吗 SERVER 我应该使用 SERVER HTTP CLIENT IP SERVER HTTP X FORWARDED FOR or SERVER REMOTE ADDR UPDATE 如果您的客
  • Xcode 4 中的这些图标代表什么?

    我以前从未见过这些 但是文件浏览器中文件名旁边的小 A 和 M 是做什么用的 让我根据SVN的知识猜测一下 A gt 新添加的文件 M gt 修改现有文件
  • 如何在 Titanium JS 中创建带有按钮的标题栏?

    我在用着钛合金构建一个应用程序 我尝试创建一个带有按钮的标题栏 类似于联系人应用程序 如下图所示 该标题的标题位于中间 按钮位于任一站点 我一直在到处寻找一种在钛中做到这一点的方法 但我还没有找到任何东西 文档中似乎没有这个内容 我需要创建
  • 如何在配置单元中保留驼峰式大小写的列名

    选择 12345 作为 EmpId 输出是 empid 值为 12345 有任何线索可以保持与 EmpId 相同的列名吗 不可能 这是 HIVE 元存储的限制 它以全小写形式存储表的模式 Hive 使用此方法来标准化列名称 请参阅表 jav
  • 内部访问修饰符与私有访问修饰符

    两者有什么区别internal and privateC 中的访问修饰符 internal适用于程序集范围 即只能从同一 exe 或 dll 中的代码访问 private适用于类范围 即只能从同一类中的代码访问
  • 为什么char数据的地址不显示?

    class Address int i char b string c public void showMap void void Address showMap void cout lt lt address of int lt lt i
  • 没有 Web 服务器的 Spring Boot

    我有一个简单的 Spring Boot 应用程序 它从 JMS 队列获取消息并将一些数据保存到日志文件中 但不需要 Web 服务器 有没有办法在没有Web服务器的情况下启动Spring Boot 春季启动 2 x 3 x 应用程序属性 sp
  • Laravel 4 不刷新

    我在 laravel 4 中遇到一个奇怪的问题 因为每次我尝试刷新页面时都不会出现更改 肯定不是浏览器的缓存 任何帮助表示赞赏 我遇到了同样的问题并找到了答案 尝试在 php ini 中禁用 OPcache 如果您使用MAMP 可以在 Ap
  • 隐藏已编译应用程序可执行代码的实践

    反编译和逆向工程 net 程序集是一种标准做法 我想发布一些将添加到现有应用程序的插件程序集 但我不希望它们被其他人使用 有哪些方法可以隐藏这些程序集的来源 除非控制目标硬件 否则理论上不可能实现 100 的保护 如果 CPU 能够执行它
  • 咖啡 | solver.prototxt值设置策略

    在 Caffe 上 我正在尝试实现一个用于语义分割的全卷积网络 我想知道是否有一个具体的策略来设置你的 solver prototxt 以下超参数的值 测试迭代器 测试间隔 迭代大小 max iter 这是否取决于您的训练集的图像数量 如果
  • c语言中绝对值的写法

    我知道该解决方案很丑陋并且在技术上不正确 但我不明白为什么代码不起作用 include
  • 包括 ACL 条件下的功能

    我有一个名为 MedicalFile 的资产 其中包含对组织的引用 参与者 HealthCareProfessional 也属于一个组织 现在我想定义一个 ACL 规则 限制医疗保健专业人员只能查看 MedicalFile 与其组织连接的医
  • Java 中 JESS 的输出

    我想将 事实 发送到java中的JESS文件并获取结果 我基本上对 JESS 文件进行批处理 然后通过 add 将我的数据 此处的结构 发送到引擎中 我试图将 JESS 结果 应该是一个字符串 转换为 值 Rete engine new R
  • Kafka 连接器和架构注册表 - 检索 Avro 架构时出错 - 未找到主题

    我有一个主题 最终会有很多不同的模式 目前它只有一个 我已经通过 REST 创建了一个连接作业 如下所示 name com mycompany sinks GcsSinkConnector auth2 config connector cl
  • 维基百科信息框需要正则表达式

    好的 这就是我需要的 我们有维基百科文章的完整 XML 我们只需要信息框部分 我尝试过各种方法 但我的主要问题似乎是无法匹配 内部 花括号 有什么想法 或者您已经设法完成此任务的任何正则表达式吗 对于那些不知道我在说什么的人 这是我试图解析
  • PDO 获取/获取全部

    对 PHP 来说并不陌生 但对 PDO 来说才刚出生一天 我肯定在这里做错了什么 query conn gt prepare SELECT FROM admins WHERE username username AND password p
  • 如何在 VBA 中将数据从访问表复制到数组?

    我正在开发一个程序 它可以从表中的一个字段中获取数据 并将整列放入数组中 甚至可以从表本身中读取数据 该代码似乎使用了表单或其他我想使用数组的东西 这将起作用 Dim rstData As DAO Recordset Dim v As Va
  • 允许 ics 在 iOS 的 PhoneGap 应用程序中打开

    所以我使用了这段代码here稍微增强一下 可以在 iOS 上动态创建 ics 文件 msgData1 start time text msgData2 end time text msgData3 Location text var ics
  • 如何在 SQL select 语句中动态创建列

    我有3张桌子 团队 选项 选项团队 团队拥有 TeamId 和 NameOption保存OptionId OptionGroupOptionTeam持有TeamId OptionId OptionGroup select a TeamId