具有联接和动态列的 SQL SERVER PIVOT 表

2024-03-24

我有一个问题需要调整,但遇到了麻烦。

SQL Server 的版本为 2005 和 2008。

查询源自公共表表达式

DECLARE 
@cols AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX),
@in_iYearFrom int, @in_iYearTo int,
@in_iMonthFrom int, @in_iMonthTo int,
@in_vsPlanID varchar(100)
@cols AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX),
@in_iYearFrom int, @in_iYearTo int,
@in_iMonthFrom int, @in_iMonthTo int,
@in_vsPlanID varchar(100)    

SELECT 
 @in_iYearFrom = 2012, @in_iYearTo = 2013, @in_iMonthFrom = 11, @in_iMonthTo = 2, @in_vsPlanID = '25,28'

select @cols = STUFF(
            (SELECT DISTINCT
                ',' + QUOTENAME(Convert(varchar(4),Year(b.run_date)) + ', ' +  DateName(month,b.run_date)) AS run_date
                FROM tblBill b
                WHERE b.plan_id IN (SELECT * FROM dbo.fnStringToTable(@in_vsPlanID,','))
                AND Year(b.run_date) * 100 + MONTH(b.run_date) >= @in_iYearFrom * 100 + @in_iMonthFrom
                AND Year(b.run_date) * 100 + MONTH(b.run_date) <= @in_iYearTo * 100 + @in_iMonthTo 
                GROUP BY b.run_date
                ORDER BY run_date
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

SET @query = N'
;WITH cteBills (total_premium, run_month, run_year, plan_id) AS
(
 SELECT 
SUM(Round(ebs.employee_premium,2) + Round(ebs.employer_premium,2) + 
    Round(ebs.ee_tax_prov,2) + Round(ebs.er_tax_prov,2) + 
    Round(ebs.ee_tax_fed,2) + Round(ebs.er_tax_fed,2) + 
    Round(ebs.ee_tax_hst,2) + Round(ebs.er_tax_hst,2)
) AS total_premium,
Month(b.run_date), Year(b.run_date), b.plan_id
FROM EmpBillStatement ebs 
INNER JOIN tblBillStatementBenefit bsb ON bsb.billstatementbenefit_id = ebs.billstatementbenefit_id
INNER JOIN tblBillStatement bs ON bs.billstatement_id = bsb.billstatement_id
INNER JOIN tblBill b ON b.bill_id = bs.bill_id
WHERE b.plan_id IN (SELECT * FROM dbo.fnStringToTable(@vsPlanID, '',''))
AND Year(b.run_date) * 100 + MONTH(b.run_date) >= @iYearFrom * 100 + @iMonthFrom
AND Year(b.run_date) * 100 + MONTH(b.run_date) <= @iYearTo * 100 + @iMonthTo 
AND b.confirmed_bill = 1
GROUP BY b.plan_id, Month(b.run_date), Year(b.run_date)
  ),
 cteBillsAdj (total_adj, run_month, run_year, plan_id) AS 
 (            
 SELECT 
   SUM(
    Round(ISNULL(adjust_cost_er,0),2) + 
    Round(ISNULL(adjust_cost_ee,0),2) +
    Round(ISNULL(adjust_tax_ee_prov,0),2) +
    Round(ISNULL(adjust_tax_er_prov,0),2) +
    Round(ISNULL(adjust_tax_ee_hst,0),2) + 
    Round(ISNULL(adjust_tax_er_hst,0),2) + 
    Round(ISNULL(adjust_tax_ee_fed,0),2) + 
    Round(ISNULL(adjust_tax_er_fed,0),2)
) AS total_premium,
Month(b.run_date), Year(b.run_date), b.plan_id
FROM tblBillAdjustmentBenefit e
INNER JOIN tblBillAdjustment ba ON (ba.billadjustment_id = e.billadjustment_id)
INNER JOIN tblBillStatementBenefit bsb ON bsb.billstatementbenefit_id = e.billstatementbenefit_id
INNER JOIN tblBillStatement bs ON bs.billstatement_id = bsb.billstatement_id                 
INNER JOIN tblBill b ON b.bill_id = bs.bill_id
WHERE b.plan_id IN (SELECT * FROM dbo.fnStringToTable(@vsPlanID, '',''))
AND Year(b.run_date) * 100 + MONTH(b.run_date) >= @iYearFrom * 100 + @iMonthFrom
AND Year(b.run_date) * 100 + MONTH(b.run_date) <= @iYearTo * 100 + @iMonthTo 
AND b.confirmed_bill = 1
GROUP BY b.plan_id, Month(b.run_date), Year(b.run_date)
)
select plan_id, ' + @cols + '
 from
 (
   SELECT 
    b.plan_id, 
    (Convert(varchar(4),b.run_year) + '', '' +  DateName(month,CAST(''1900-'' + Convert(varchar(2),b.run_month) + ''-01'' AS DATETIME))) AS billdate, 
    ISNULL(b.total_premium,0) + ISNULL(a.total_adj,0) AS total
FROM cteBills b
LEFT JOIN cteBillsAdj a 
    ON a.run_month = b.run_month 
    AND b.run_year = a.run_year 
    AND b.plan_id = a.plan_id        
) d
pivot
(
  sum(total)
  for billdate in (' + @cols + ')
) piv;
'
execute sp_executesql @query, N'@iYearFrom int, @iYearTo int, @iMonthFrom int, @iMonthTo int, @vsPlanID varchar(100)', 
                                @in_iYearFrom, @in_iYearTo, @in_iMonthFrom, @in_iMonthTo, @in_vsPlanID;

数据显示是这样的

plan_id     billdate                             total
----------- ------------------------------------ -------------
25          2012, November                       60117.56000
25          2012, December                       61515.17000
25          2013, January                        60791.62000
25          2013, February                       60745.29000
28          2012, November                       1564.69000
28          2012, December                       1564.69000
28          2013, January                        1564.69000
28          2013, February                       1590.44000

我需要它采用这种格式

plan_id     2012, November   2012, December   2013, January   2013, February
-----------------------------------------------------------------------------
25          60117.56000      61515.17000      60791.62000     60745.29000
28          1564.69000       1564.69000       1564.69000      1590.44000

可以有更多的 plan_id 和更多的日期来跨越。

先感谢您


由于您想要将数据从行转换为列,那么您将需要使用PIVOT http://msdn.microsoft.com/en-us/library/ms177410%28v=sql.105%29.aspx功能。如果您的数量有限或已知值,则可以对查询进行硬编码:

select plan_id, [2012, November], [2012, December], [2013, January], [2013, February]
from
(
    SELECT 
        b.plan_id, 
        (Convert(varchar(4),b.run_year) + ', ' +  DateName(month,CAST('1900-' + Convert(varchar(2),b.run_month) + '-01' AS DATETIME))) AS billdate, 
        ISNULL(b.total_premium,0) + ISNULL(a.total_adj,0) AS total
    FROM cteBills b
    LEFT JOIN cteBillsAdj a 
        ON a.run_month = b.run_month 
        AND b.run_year = a.run_year 
        AND b.plan_id = a.plan_id
) d
pivot
(
    sum(total)
    for billdate in ([2012, November], [2012, December], [2013, January], [2013, February])
) piv;

但如果你有未知数量的值,那么你将需要实现动态 SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT  ',' + QUOTENAME(Convert(varchar(4),b.run_year) + ', ' +  DateName(month,CAST('1900-' + Convert(varchar(2),b.run_month) + '-01' AS DATETIME))) ) 
                    from cteBills
                    group by b.run_year, b.run_month
                    order by b.run_year, b.run_month
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT plan_id, ' + @cols + ' 
            from 
             (
                SELECT 
                    b.plan_id, 
                    (Convert(varchar(4),b.run_year) + '', '' +  DateName(month,CAST(''1900-'' + Convert(varchar(2),b.run_month) + ''-01'' AS DATETIME))) AS billdate, 
                    ISNULL(b.total_premium,0) + ISNULL(a.total_adj,0) AS total
                FROM cteBills b
                LEFT JOIN cteBillsAdj a 
                    ON a.run_month = b.run_month 
                    AND b.run_year = a.run_year 
                    AND b.plan_id = a.plan_id
            ) x
            pivot 
            (
                sum(total)
                for billdate in (' + @cols + ')
            ) p '

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

具有联接和动态列的 SQL SERVER PIVOT 表 的相关文章

  • 有没有办法以编程方式轻松更改多个 SSIS 包上的服务器名称?

    作为发布周期的一部分 我们正在创建多个 SSIS 包来迁移大型数据库 我们最终可能会得到大约 5 10 个 SSIS 包 由于我们有 4 个环境 开发 QA 登台 生产等 是否有一种有效的方法可以在每个 SSIS 包经历不同的服务器环境时更
  • 为什么 SqlClient 在传递 SqlXml 时使用不必要的 XML 转换?

    我有一个关于从 C 代码将 xml 数据类型传递给查询的问题 首先 这是 SQL Server 上的一个表 CREATE TABLE dbo XmlTable id int IDENTITY 1 1 NOT NULL dat xml NOT
  • 如何在 SQL Server 存储过程中对用户定义的表类型执行 ForEach?

    XX PROCEDURE dbo XXX X dbo IntType readonly AS BEGIN SET NOCOUNT ON how can I foreach X here and do process individually
  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • 为什么我的 CASE 语句要求 THEN 部分的数据类型为 INT?

    我正在尝试运行一个查询 其中以下 CASE 语句是其中一行 我正在使用报表生成器 3 0 但是 我收到一条错误消息 将 varchar 值 Case 1 转换为 int 数据类型时转换失败 Microsoft SQL Server 错误 2
  • 如何修改现有表以添加时区

    我有一个包含 500 多个表的大型应用程序 我必须将应用程序转换为时区感知 当前应用程序使用new java util Date GETDATE 与服务器的时区 即没有任何时区支持 我已将这项任务分为几个步骤 以便于开发 我确定的第一个步骤
  • 普通表还是全局临时表?

    我和另一位开发人员正在讨论哪种类型的表更适合我们的任务 它基本上是一个我们将在一天结束时截断的缓存 就我个人而言 我认为没有任何理由为此使用除普通表之外的任何内容 但他想使用全局临时表 其中之一有什么优点吗 使用普通表tempdb如果这只是
  • 在 SQL 中将数字求小数次幂

    我试图在 MS SQL 中将一系列数字求小数 1 5 次幂 但在应用于负基数时出现 域错误 这应该不是问题 因为我要提升到奇次幂根 此外 我可以在 Excel 中进行计算 谁能评论一下 MS SQL 是否根本不支持将负幂提高到小数根 负基数
  • 在工作表中合并行和求和值

    我有一个 Excel 工作表 其中包含以下数据 管道 来分隔列 A B C X 50 60 D E F X 40 30 A B C X 10 20 A B C Y 20 20 A B C X 20 70 D E F X 10 50 A B
  • 将 SQL Server 与 Dart 结合使用

    我还没有找到很好的答案 所以我想尝试一下得到答案 将 Microsoft SQL Server 与 Dart 结合使用的最佳方式是什么 我需要它能够从基本上任何操作系统 网络和移动设备上使用它 我觉得最好的方法可能是 GraphQL 但我对
  • 如何在实体框架中完全锁定一行

    我正在处理的情况是我们正在处理金钱交易 例如 我有一个用户钱包表 其余额位于该行 UserId Wallet Id Balance 现在 在我们的网站和网络服务中 每次发生特定交易时 我们都需要 检查是否有足够的资金可用于执行该交易 从余额
  • 数据库未在客户端系统上运行的 C# Windows 窗体应用程序

    我用 C 开发了一个使用 SQL Server 数据库连接的 Windows 窗体应用程序 我在 NET Framework 4 0 和 SQL Server 2008 R2 中开发它 我的应用程序正在使用应用程序根目录中存在的本地数据库
  • 在c#中创建sql连接

    我是这个网站的新手 也是编程的新手 我目前正在通过销售点创建库存系统 它使用模态和非模态形式 我的问题是 我正在研究change password对话框必须连接到数据库才能覆盖密码字段 我使用的数据库是Microsoft SQL Serve
  • T-SQL:用最新的非空值替换 NULL 的最佳方法?

    假设我有这张表 id value 1 5 2 4 3 1 4 NULL 5 NULL 6 14 7 NULL 8 0 9 3 10 NULL 我想编写一个查询来替换任何NULL值与表中最后一个不为空的值在那一栏里 我想要这个结果 id va
  • C# 中处理 SQL 死锁的模式?

    我正在用 C 编写一个访问 SQL Server 2005 数据库的应用程序 该应用程序是数据库密集型的 即使我尝试优化所有访问 设置适当的索引等 我预计迟早会遇到死锁 我知道为什么会发生数据库死锁 但我怀疑我能否在某个时候发布不发生死锁的
  • SQL Server 连接其他表中不存在的位置

    Service Asset AssetService Id Name Id Name AssetId ServiceId
  • 解析带下划线的 SQL Server 数字文字

    我想知道它为什么有效以及为什么它不返回错误 SELECT 2015 11 Result 11 2015 第二种情况 SELECT 2 1 a a 2 1 检查元数据 SELECT name system type name FROM sys
  • SQL查询查找表的主键?

    我怎样才能找到哪一列首要的关键使用查询来创建表 这是重复的question https stackoverflow com questions 893874 mysql determine tables primary key dynami
  • 如何在 SQL Server 中连接

    我的数据库没有特定的列 因此我通过开关在查询中创建了一个列 我需要的是将此列与数据库中的另一列连接起来 select certificateDuration DurationType case when certificateDuratio
  • 想要编写依赖于 SQL Server 表的所有对象的脚本

    查看依赖关系 显示依赖于 SQL Server 中的表的所有对象 现在 我如何使用 SSMS 在一个命令中编写所有这些对象的脚本 有没有免费的工具可以做到这一点 首先你可以尝试这个链接了解 SQL 依赖关系 http msdn micros

随机推荐