请帮我解决这个问题。我完全陷入困境。我有编码员阻止或其他什么。
我有下表
ID Name Cost Included
---- ---------- ------- ----------
1 Package1 10.00 Yes
2 Package2 20.00 No
3 Package3 20.00 Yes
我想交叉显示此信息,要显示如下例子,表格中会有更多列。
Type Package1 Package2 Package3
----- ------------ ----------- ----------
Name Package1 Package2 Package3
Cost 10.00 20.00 30.00
Included Yes No Yes
答案 0 :(得分:5)
在我看来,您正在尝试构建产品比较列表。如果是这样,您可以先unpivot表格,然后将各个记录合并在一起。
'transponded'部分对列进行展开。所有列必须是兼容类型或转换为一个。我选择varchar(100)。 transponded返回表,包含三列,来自ProductInfo的ID,Type作为列名,Value作为相应列的值。
通过添加另一个left join transponded tn on t1.Type = tnType and tn.ID = @parametern
,选择部件将所需产品的信息连接在一起。这部分似乎很麻烦,但是当我尝试使用pivot执行此部分时,我无法按正确的顺序获取列 - 在Type中透视排序的名称。但是它需要动态的sql生成。此解决方案已修复,前提是您可以为希望一次比较的最大产品添加足够的连接。我相信它不会超过5。
= 1,= 2且= 3应由参数替换。查询应该存储在存储过程中。
; with transponded as
(
select ID, Type, Value
from
(
select ID,
Name,
cast (Cost as varchar(100)) Cost,
cast (case when Included = 1 then 'Yes' else 'No' end as varchar(100)) Included
from ProductInfo
) p
unpivot (Value for Type in (Name, Cost, Included) ) a
)
select t1.Type,
t1.Value Product1,
t2.Value Product2,
t3.Value Product3
from transponded t1
left join transponded t2
on t1.Type = t2.Type
and t2.id = 2
left join transponded t3
on t1.Type = t3.Type
and t3.id = 3
where t1.id = 1
简而言之,一次转发一条记录,然后按类型列加入另一条转发记录。
答案 1 :(得分:1)
没有简单的方法可以做到这一点,因为枢轴需要按列聚合。鉴于在输入表中添加列会导致维护问题,这些值将不会显示到输出,直到代码在任何地方使用时都会更改,我会说你最好用存储过程执行一次,它将根据输入表的模式动态生成您正在查找的输出。
我已经使用您提供的数据演示了如何做到这一点。这些数据存储在临时表中(不是#temp,因为存储的proc不能用于临时表),因此填充:
CREATE TABLE temp (
_key int,
package_name varchar(50),
cost float,
included bit
)
INSERT INTO temp VALUES(1,'Package1', 10.00, 1)
INSERT INTO temp VALUES(2,'Package2', 20.00, 0)
INSERT INTO temp VALUES(3,'Package3', 20.00, 1)
存储过程根据@pivot_field参数检索值列表,并将这些值用作要在“类型”字段后插入的列列表。然后它将枢轴字段和所有其他字段组合在一起以生成行,一次旋转一列。程序如下:
CREATE PROCEDURE usp_get_pivot (@table_name nvarchar(255), @pivot_field nvarchar(255)) AS
BEGIN
CREATE TABLE #temp (val nvarchar(max))
DECLARE @sql NVARCHAR(MAX), @cols NVARCHAR(MAX), @col NVARCHAR(255)
SET @sql = 'SELECT DISTINCT ' + @pivot_field + ' FROM ' + @table_name
INSERT INTO #temp EXEC sp_executesql @sql;
SET @cols = (SELECT '[' + val + '],' FROM #temp FOR XML PATH(''))
SET @cols = SUBSTRING(@cols, 1, LEN(@cols)-1)
SET @SQL = N'SELECT ''' + @pivot_field + ''' as [type], *
FROM (SELECT ' + @pivot_field + ', ' + @pivot_field + ' as ' + @pivot_field + '1 FROM ' + @table_name + ') AS source_table
PIVOT (max(' + @pivot_field + '1) FOR ' + @pivot_field + ' IN (' + @cols + ')) AS pivot_table'
DECLARE csr CURSOR FOR
SELECT c.name FROM sys.columns c, sys.objects o
WHERE c.object_id = o.object_id AND o.name = @table_name
AND c.name <> @pivot_field
ORDER BY column_id
OPEN csr
FETCH NEXT FROM csr INTO @col
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = @sql + ' UNION ALL
SELECT ''' + @col + ''' as [type], *
FROM (SELECT ' + @pivot_field + ', CAST(' + @col + ' AS VARCHAR) AS ' + @col + ' FROM ' + @table_name + ') AS source_table
PIVOT (max(' + @col + ') FOR ' + @pivot_field + ' IN (' + @cols + ')) AS pivot_table'
FETCH NEXT FROM csr INTO @col
END
CLOSE csr
DEALLOCATE csr
DROP TABLE #temp
EXEC sp_executesql @sql
END
您应该能够简单地将程序复制并粘贴到管理工作室,创建上面显示的数据并执行以下程序:
EXEC usp_get_pivot 'temp', 'package_name'
答案 2 :(得分:0)
如果包的数量不是静态的,我认为没有选择。 PIVOT
子句只能生成静态/定义的列数。
您可以使用多个语句进行一些表到表的重写 - 但仍然需要面对静态列数。
但是你可以将其设置为例如10,然后显示最多10个包,如果包含的数量较少,则在其余列中显示NULL-s。
您也可以使用动态SQL来获得动态列数 - 但这将是一个令人头疼的问题。
如果您要将此数据导出到Excel - 请勿在SQL处进行转移 - 在Excel中进行转置(在“粘贴特殊”下)。
答案 3 :(得分:0)
基本上我现阶段所拥有的是以下内容。
SELECT [Type],
MAX(Beginner) AS [Beginner],
MAX(Intermediate) AS [Intermediate],
MAX(Advanced) AS [Advanced]
FROM
(
SELECT
'Name' AS TYPE,
CASE WHEN Name='Beginner' THEN Name END AS [Beginner],
CASE WHEN Name='Intermediate' THEN Name END AS [Intermediate],
CASE WHEN Name='Advanced' THEN Name END AS [Advanced]
FROM Administration.Package
UNION ALL
SELECT
'Price' AS TYPE,
CASE WHEN Name='Beginner' THEN CAST(Price AS VARCHAR) END AS [Beginner],
CASE WHEN Name='Intermediate' THEN CAST(Price AS VARCHAR) END AS [Intermediate],
CASE WHEN Name='Advanced' THEN CAST(Price AS VARCHAR) END AS [Advanced]
FROM Administration.Package
)A
GROUP BY [Type]
但是对每一栏都有联盟感觉不对。