Leo*_*Lai 9 t-sql pivot sql-server-2005 dynamic-data sql-server-2008
我正在使用SQL Server(T-sql)中的动态列的pvots进行SQL查询.我没有提交冗长的查询,而是用简化的模型来说明我的问题.
我创建了2个表:Table1和Table2,并用几个条目填充它们,如下所示:
表格1:
Col_ID1 ............... COL_NAME
1 .........................扬11
2 ......................... FEB-11
3 ......................... 3月-11
表2:
Col_ID2 ......帐户.....帐户名......额
1 ............... 121 ...........电力............万
2 ............... 121 ...........电力............ 20000
3 ............... 121 ...........电力............ 30000
1 ............... 122 ...........电话.............. 100
2 ............... 122 ...........电话.............. 200
3 ............... 122 ...........电话.............. 300
我正在创建一个Pivot,但我希望以参数方式生成列名(基于输入屏幕中键入的日期),而不是硬编码.
下面的查询效果很好,但只提供了几列作为foll:
扬11 ...........月 - 11月........... 11
10,000.00 20,000.00 ...... 30,000.00 ......
100.00 200.00 ............... 300.00 ...........
我希望查询也返回描述性列,如下所示:
账户...........帐户名...........月11 ............月11 ........ ...... MAR-11
121 .................电力.................. 10,000.00 20,000.00 ...... ..... ..... 30,000.00
122 .................电话..................... 100.00 ......... ..200.00 ............. 300.00
有人可以帮我修改我的查询,以便达到我的目标吗?
此查询是对Andras博士于2007年9月撰写的以下文章的改编 .http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx
有人评论说代码可能会受到注入攻击,并建议使用Quotename函数而不是连接方括号.
你能解释一下如何在我的查询中使用Quotename吗?
非常感谢,
莱昂莱.
.
.
这是我的查询:
------------------------ create&populate table1 ---------------------- ----------
CREATE TABLE Table1
(Col_ID1 INT,
Col_Name varchar(10))
INSERT INTO Table1 VALUES (1, 'Jan-11')
INSERT INTO Table1 VALUES (2, 'Feb-11')
INSERT INTO Table1 VALUES (3, 'Mar-11')
Run Code Online (Sandbox Code Playgroud)
------------------------- create&populate table2 --------------------- -------------
CREATE TABLE Table2
(Col_ID2 INT,
Account varchar(10),
AccountName varchar(20),
Amount numeric(18,6))
INSERT INTO Table2 VALUES (1, 121, 'Electricity', 10000)
INSERT INTO Table2 VALUES (2, 121, 'Electricity', 20000)
INSERT INTO Table2 VALUES (3, 121, 'Electricity', 30000)
INSERT INTO Table2 VALUES (1, 122, 'Telephone', 100)
INSERT INTO Table2 VALUES (2, 122, 'Telephone', 200)
INSERT INTO Table2 VALUES (3, 122, 'Telephone', 300)
Run Code Online (Sandbox Code Playgroud)
----------------------------------创建列标题------------- ------
DECLARE @cols NVARCHAR(2000)
SELECT @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
'],[' + t2.Col_Name
FROM Table1 AS t2
ORDER BY '],[' + t2.Col_Name
FOR XML PATH('')
), 1, 2, '') + ']'
Run Code Online (Sandbox Code Playgroud)
------------------------------------- create @query ---------- ------------
DECLARE @query NVARCHAR(4000)
SET @query = N'SELECT '+
@cols +'
FROM
Run Code Online (Sandbox Code Playgroud)
--------------------------子查询-----
(SELECT
t1.Col_Name,
t2.Account,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p
-------------------- pivot -------------------------
PIVOT
(
Sum ([Amount] )
FOR Col_Name IN
( '+
@cols +' )
) AS pvt '
---------------------- exec&drop ----------
EXECUTE(@query)
drop table table1
drop table table2
Run Code Online (Sandbox Code Playgroud)
================================================== =====
嗨菲利普,
非常感谢您的回复.
您提出的查询工作顺利,并生成预期的屏幕,但它不是我想要的.
首先,感谢代码:SELECT @cols = isnull(@cols +',','')+'['+ Col_Name +']'
它更简单,并取代我的涉及东西和xml路径的行,显然具有相同的效果.
让我解释一下我想做什么.
我想在Sap Business 1(一个会计软件包 - 或称之为ERP)中开发一个查询.Sap在Microsoft Server 2008中使用T-sql,并拥有自己的查询生成器.除了极少数例外,Sap sql类似于T-sql.
我希望我的查询能够在12个月内逐月列出所有收入和支出.
但是,我不希望我的列标题被硬编码(因为这需要我不时修改我的查询),如下所示:
1月11日,2月11日,3月11日,4月11日,11月11日
相反,我希望从用户在输入屏幕中输入的日期动态生成列标题.
正如我所提到的,我在论坛上发布的查询是我的真实查询的过度简化版本,仅用于说明.真实查询包含多个变量,输入屏幕(在Sap b1中称为查询 - 选择标准框)允许用户输入日期.这个日期将用于动态确定列名.
这就是为什么我需要像@cols,@ query,pivot等这样复杂的工具.
如果我在输入屏幕中输入'01 .06.11'(2011年6月1日),则此日期将传递给sql,后者将确定列标题的名称为foll:
6月11日,7月11日,8月11日..... 5月12日.
如果我输入另一个日期,比如'01 .09.10'(2010年9月1日),则列标题将更改为:
9月10日,10月10日,.... 8月11日
看来你已经对我的列标题进行了硬编码.
您是否可以再次查看我的查询,并提出一些允许以参数方式生成列名而不是硬编码的内容?
谢谢
莱昂莱
Phi*_*ley 11
添加这些列非常简单.最后的查询是
SELECT Account, AccountName, [Feb-11],[Jan-11],[Mar-11] FROM
(SELECT
t1.Col_Name,
t2.Account,
t2.AccountName,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p
PIVOT
(
Sum ([Amount] )
FOR Col_Name IN
( [Feb-11],[Jan-11],[Mar-11] )
) AS pvt
Run Code Online (Sandbox Code Playgroud)
将t2.AccountName添加到子查询中,并将Account和AccountName添加到初始SELECT中.将它们放入构建语句中,您就完成了:
DECLARE @query NVARCHAR(4000)
SET @query = N'SELECT Account, AccountName, ' + @cols +' FROM
(SELECT
t1.Col_Name,
t2.Account,
t2.AccountName,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p
PIVOT
(
Sum ([Amount] )
FOR Col_Name IN
( '+
@cols +' )
) AS pvt '
Run Code Online (Sandbox Code Playgroud)
至于SQL注入,我可以看到发生这种情况的唯一方法是,如果有人以某种方式在Table1.Col_Name中嵌入恶意代码,并且如果你不得不担心这一点,那么你比"锁定"这个动态查询有更大的问题.
另外值得一提的是,我将使用以下内容来构建列列表(@Cols),因为它更短更容易阅读,但主要是因为我不喜欢XML.
DECLARE @cols NVARCHAR(2000)
SELECT @cols = isnull(@cols + ',', '') + '[' + Col_Name + ']'
FROM Table1
ORDER BY Col_Name
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34495 次 |
最近记录: |