我已经尝试了一段时间来使用SQL Server数据透视表,但我似乎并没有把它做对。我已经阅读了一堆SO答案,但不明白枢轴是如何工作的。
我正在编写存储过程。我有表1(作为TVP收到),需要看起来像表2(see this image for tables)。
重要说明:Table1.valueTypeID中的值无法硬编码到逻辑中,因为它们总是可以更改。因此,逻辑必须是超级动态的。
请参阅下面的代码。枢轴位于存储过程的末尾。
-- Create date: 12/10/2013
-- Description: select all the contacts associated with received accountPassport
-- =============================================
ALTER PROCEDURE [dbo].[selectContactsPropsByAccountPassport]
-- Add the parameters for the stored procedure here
@accountPassport int,
@valueTypeFiltersTVP valueTypeFiltersTVP READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE @accountID int;
DECLARE @contactsAppAccountPassport int;
DECLARE @searchResults TABLE
(
resultContactID int
);
DECLARE @resultContactID int;
DECLARE @contactsPropsForReturn TABLE
(
contactID int,
valueTypeID int,
value varchar(max)
);
create table #contactsPropsForReturnFiltered(contactID int,valueTypeID int, value varchar(max))
/*
DECLARE #contactsPropsForReturnFiltered TABLE
(
contactID int,
valueTypeID int,
value varchar(max)
);
*/
--2. get @contactsAppAccountPassport associated with recieved @accountPassport
-- go into dbo.accounts and get the @accountID associated with this @accountPassport
SELECT
@accountID = ID
FROM
dbo.accounts
WHERE
passport = @accountPassport
-- go into dbo.accountsProps and get the value (@contactsAppAccountPassport) where valueType=42 and accountID = @accountID
SELECT
@contactsAppAccountPassport = value
FROM
dbo.accountsProps
WHERE
(valueTypeID=42) AND (accountID = @accountID)
--3. get all the contact ID's from dbo.contacts associated with @contactsAppAccountPassport
INSERT INTO
@searchResults
SELECT
ID
FROM
dbo.contacts
WHERE
contactsAppAccountPassport = @contactsAppAccountPassport
--4. Get the props of all contact ID's from 3.
--start for each loop....our looping object is @resultContactID row. if there are more rows, we keep looping.
DECLARE searchCursor CURSOR FOR
SELECT
resultContactID
FROM
@searchResults
OPEN searchCursor
FETCH NEXT FROM searchCursor INTO @resultContactID
WHILE (@@FETCH_STATUS=0)
BEGIN
INSERT INTO
@contactsPropsForReturn
SELECT
contactID,
valueTypeID,
value
FROM
dbo.contactsProps
WHERE
contactID = @resultContactID
FETCH NEXT FROM searchCursor INTO @resultContactID
END --end of WHILE loop
--end of cursor (both CLOSE and DEALLOCATE necessary)
CLOSE searchCursor
DEALLOCATE searchCursor
-- select and return only the props that match with the requested props
-- (we don't want to return all the props, only the ones requested)
INSERT INTO
#contactsPropsForReturnFiltered
SELECT
p.contactID,
p.valueTypeID,
p.value
FROM
@contactsPropsForReturn as p
INNER JOIN
@valueTypeFiltersTVP as f
ON
p.valueTypeID = f.valueTypeID
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(ValueTypeId)
FROM #contactsPropsForReturnFiltered
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set @query = 'SELECT contactid, ' + @cols + ' from
(
select contactid
, Value
,ValueTypeId
from #contactsPropsForReturnFiltered
) x
pivot
(
min(Value)
for ValueTypeId in (' + @cols + ')
) p ';
execute(@query);
END
答案 0 :(得分:2)
您需要在案例中使用动态数据透视。请尝试以下
create table table1
(
contactid int,
ValueTypeId int,
Value varchar(100)
);
insert into table1 values (56064, 40, 'Issac');
insert into table1 values (56064, 34, '(123)456-7890');
insert into table1 values (56065, 40, 'Lola');
insert into table1 values (56065, 34, '(123)456-7832');
insert into table1 values (56068, 40, 'Mike');
insert into table1 values (56068, 41, 'Gonzalez');
insert into table1 values (56068, 34, '(123)456-7891');
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(ValueTypeId)
FROM table1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set @query = 'SELECT contactid, ' + @cols + ' from
(
select contactid
, Value
,ValueTypeId
from table1
) x
pivot
(
min(Value)
for ValueTypeId in (' + @cols + ')
) p ';
execute(@query);
drop table table1
答案 1 :(得分:0)
为什么需要以这种方式呈现数据?
在许多情况下,客户端比数据库引擎更好地进行数据透视。例如,SQL Server Reporting Services可以使用矩阵控件轻松完成此操作。同样,如果您在Asp.Net中对网页进行编码,则可以快速运行记录集以将数据传递到新的数据表示形式(同时收集唯一值),然后一次性通过新数据对象吐出HTML来呈现结果。
如果可能,请让您的客户端进行透视而不是服务器。
<强>更新
如果你真的想在动态SQL中使用表变量,你可以在SQL Server 2008及更高版本中使用。这是一个示例脚本:
USE tempdb
GO
CREATE TYPE IDList AS TABLE (
ID int
);
GO
DECLARE @SQL nvarchar(max);
SET @SQL = 'SELECT * FROM @TransactionIDs WHERE ID >= 4;'
DECLARE @TransactionIDs IDLIst;
INSERT @TransactionIDs VALUES (1), (2), (4), (8), (16);
EXEC sp_executesql @SQL, N'@TransactionIDs IDList READONLY', @TransactionIDs;
GO
DROP TYPE IDList;