目前在SQL Server 2008中构建SELECT
语句但希望使此SELECT
语句动态化,因此可以根据表中的值来定义列。我听说过数据透视表和游标,但在我目前的水平上似乎有点难以理解,这是代码;
DECLARE @date DATE = null
IF @date is null
set @ date = GETDATE() as DATE
SELECT
Name,
value1,
value2,
value3,
value4
FROM ref_Table a
FULL OUTER JOIN (
SELECT
PK_ID ID,
sum(case when FK_ContainerType_ID = 1 then 1 else null) Box,
sum(case when FK_ContainerType_ID = 2 then 1 else null) Pallet,
sum(case when FK_ContainerType_ID = 3 then 1 else null) Bag,
sum(case when FK_ContainerType_ID = 4 then 1 else null) Drum
from
Packages
WHERE
@date between PackageStart AND PackageEnd
group by PK_ID ) b on a.Name = b.ID
where
Group = 0
以下对我很有用,但PK_Type_ID和列名(PackageNameX,..)是硬编码的,我需要是动态的,它可以根据{{1}中的当前或期货值构建自己} table。
非常感谢任何有关正确方向的帮助或指导......
根据要求
Package
(PK_ID,姓名)
ref_Table
1, John
2, Mary
3, Albert
4, Jane
(PK_ID,FK_ref_Table_ID,FK_ContainerType_ID,PackageStartDate,PackageEndDate)
Packages
1 , 1, 4, 1JAN2014, 30JAN2014
2 , 2, 3, 1JAN2014, 30JAN2014
3 , 3, 2, 1JAN2014, 30JAN2014
4 , 4, 1, 1JAN2014, 30JAN2014
(PK_ID,类型)
ContainerType
,结果应如下所示;
1, Box
2, Pallet
3, Bag
4, Drum
我说的以下代码效果很好,问题是Name Box Pallet Bag Drum
---------------------------------------
John 1
Mary 1
Albert 1
Jane 1
表会增长,我需要复制相同的报告而不对列进行硬编码。
答案 0 :(得分:1)
您需要构建的内容称为动态数据透视。如果您搜索该术语,Stack上有很多很好的参考资料。
以下是您的方案的解决方案:
IF OBJECT_ID('tempdb..##ref_Table') IS NOT NULL
DROP TABLE ##ref_Table
IF OBJECT_ID('tempdb..##Packages') IS NOT NULL
DROP TABLE ##Packages
IF OBJECT_ID('tempdb..##ContainerType') IS NOT NULL
DROP TABLE ##ContainerType
SET NOCOUNT ON
CREATE TABLE ##ref_Table (PK_ID INT, NAME NVARCHAR(50))
CREATE TABLE ##Packages (PK_ID INT, FK_ref_Table_ID INT, FK_ContainerType_ID INT, PackageStartDate DATE, PackageEndDate DATE)
CREATE TABLE ##ContainerType (PK_ID INT, [Type] NVARCHAR(50))
INSERT INTO ##ref_Table (PK_ID,NAME)
SELECT 1,'John' UNION
SELECT 2,'Mary' UNION
SELECT 3,'Albert' UNION
SELECT 4,'Jane'
INSERT INTO ##Packages (PK_ID, FK_ref_Table_ID, FK_ContainerType_ID, PackageStartDate, PackageEndDate)
SELECT 1,1,4,'2014-01-01','2014-01-30' UNION
SELECT 2,2,3,'2014-01-01','2014-01-30' UNION
SELECT 3,3,2,'2014-01-01','2014-01-30' UNION
SELECT 4,4,1,'2014-01-01','2014-01-30'
INSERT INTO ##ContainerType (PK_ID, [Type])
SELECT 1,'Box' UNION
SELECT 2,'Pallet' UNION
SELECT 3,'Bag' UNION
SELECT 4,'Drum'
DECLARE @DATE DATE, @PARAMDEF NVARCHAR(MAX), @COLS NVARCHAR(MAX), @SQL NVARCHAR(MAX)
SET @DATE = '2014-01-15'
SET @COLS = STUFF((SELECT DISTINCT ',' + QUOTENAME(T.[Type])
FROM ##ContainerType T
FOR XML PATH, TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @SQL = 'SELECT [Name], ' + @COLS + '
FROM (SELECT [Name], [Type], 1 AS Value
FROM ##ref_Table R
JOIN ##Packages P ON R.PK_ID = P.FK_ref_Table_ID
JOIN ##ContainerType T ON P.FK_ContainerType_ID = T.PK_ID
WHERE @DATE BETWEEN P.PackageStartDate AND P.PackageEndDate) X
PIVOT (COUNT(Value) FOR [Type] IN (' + @COLS + ')) P
'
PRINT @COLS
PRINT @SQL
SET @PARAMDEF = '@DATE DATE'
EXEC SP_EXECUTESQL @SQL, @PARAMDEF, @DATE=@DATE
输出:
Name Bag Box Drum Pallet
Albert 0 0 0 1
Jane 0 1 0 0
John 0 0 1 0
Mary 1 0 0 0
答案 1 :(得分:-1)
静态查询:
SELECT [Name],[Box],[Pallet],[Bag],[Drum] FROM
(
SELECT *
FROM
(
SELECT rf.Name,cnt.[Type], pk.PK_ID AS PKID, rf.PK_ID AS RFID
FROM ref_Table rf INNER JOIN Packages pk ON rf.PK_ID = pk.FK_ref_Table_ID
INNER JOIN ContanerType cnt ON cnt.PK_ID = pk.FK_ContainerType_ID
) AS SourceTable
PIVOT
(
COUNT(PKID )
FOR [Type]
IN ( [Box],[Pallet],[Bag],[Drum])
) AS PivotTable
) AS Main
ORDER BY RFID
动态查询:
DECLARE @columnList nvarchar (MAX)
DECLARE @pivotsql nvarchar (MAX)
SELECT @columnList = STUFF(
(
SELECT ',' + '[' + [Type] + ']'
FROM ContanerType
FOR XML PATH( '')
)
,1, 1,'' )
SET @pivotsql =
N'SELECT [Name],' + @columnList + ' FROM
(
SELECT *
FROM
(
SELECT rf.Name,cnt.[Type], pk.PK_ID AS PKID, rf.PK_ID AS RFID
FROM ref_Table rf INNER JOIN Packages pk ON rf.PK_ID = pk.FK_ref_Table_ID
INNER JOIN ContanerType cnt ON cnt.PK_ID = pk.FK_ContainerType_ID
) AS SourceTable
PIVOT
(
COUNT(PKID )
FOR [Type]
IN ( ' + @columnList + ')
) AS PivotTable
) AS Main
ORDER BY RFID;'
EXEC sp_executesql @pivotsql
按照以下教程将帮助您了解PIVOT功能:
我们编写sql查询以便从数据库表中获取不同的结果集,如完整,部分,计算,分组,排序等。但是,有时我们需要旋转表格。听起来很混乱?
让我们保持简单,并考虑以下两个屏幕抓取。
SQL表:
预期结果
哇,这看起来像很多工作!这是一个棘手的SQL,临时表,循环,聚合......,等等等等的组合别担心让我们保持简单,愚蠢( KISS )。
MS SQL Server 2005及更高版本有一个名为PIVOT的函数。它使用起来非常简单,功能强大。借助此函数,我们将能够旋转sql表和结果集。
实现目标的简单步骤:
因此,如果我们现在按照以上四个步骤从上面的销售表中提取信息,它将如下所示:
如果上述所有步骤到目前为止对我们有意义的话,我们几乎就在那里。
现在我们拥有了所需的所有信息。我们现在要做的就是在下面的模板中填写所需的信息。 的模板:强> 我们的SQL查询应如下所示:
SELECT *
FROM
(
SELECT SalesYear, SalesMonth,Amount
FROM Sales
) AS SourceTable
PIVOT
(
SUM(Amount )
FOR SalesMonth
IN ( [Jan],[Feb] ,[Mar],
[Apr],[May],[Jun] ,[Jul],
[Aug],[Sep] ,[Oct],[Nov] ,[Dec])
) AS PivotTable;
在上面的查询中,我们对列名进行了硬编码。当你必须指定一些列时,它并不好玩。
但是,有一项工作如下:
DECLARE @columnList nvarchar (MAX)
DECLARE @pivotsql nvarchar (MAX)
SELECT @columnList = STUFF(
(
SELECT ',' + '[' + SalesMonth + ']'
FROM Sales
GROUP BY SalesMonth
FOR XML PATH( '')
)
,1, 1,'' )
SET @pivotsql =
N'SELECT *
FROM
(
SELECT SalesYear, SalesMonth,Amount
FROM Sales
) AS SourceTable
PIVOT
(
SUM(Amount )
FOR SalesMonth
IN ( ' + @columnList +' )
) AS PivotTable;'
EXEC sp_executesql @pivotsql
希望本教程能够帮助某个人。 享受编码。