情况: 3个源表:
1。用户(包含唯一ID和用户特定属性,如firstName
,givenName
,StreetAddress
等)
2。 MigrationFeatures (包含唯一ID和Feature_Name
)
第3。 Link_Users_and_Features (包含来自Users
和Features
的唯一ID以及Status
列(int))
在链接表中,对于每个用户,行数与Feature
表中的行数完全相同,并且每个行(每个用户)只链接到一个Feature
。每个链接行还包含一个状态值列,该列可以具有不同的值 - 根据特定用户的特定Feature
的迁移状态。
目标:
拥有一个完全动态的查询/ SP,为每个用户返回一行,并为该特定用户提供每个Feature
的迁移状态 - 每个迁移状态列将根据来自的Feature_Name
命名来自Feature
表的相应Features
。当我在Feature
表中添加额外的Feature
时,不必手动修改所需的查询代码。
提示:Feature
表已经有一个插入触发器,它为每个用户创建了这个附加列,并且相关列上存在参照完整性,因此所有用户将始终拥有所有{的链接表中的所有相应行{1}}。
我为什么要这样做:
到目前为止,我有一个包含所有用户特定列(Features
等)的表,以及所有迁移功能状态列(Name, givenName, StreetAddress,
等),其中包含所有迁移状态数据所有用户。
不幸的是,这是完全静态的,每当我添加新的SIDhist migrated, homefolder migrated,
时,我都必须修改这个主表。将来,技能较低的人员将使用底层系统,他们不会进入数据库代码或模式,只会将记录添加到Feature
和Feature
表中。
这里是创建用户DB的代码:
user
这里是创建Features表的代码:
CREATE TABLE [dbo].[Users](
[Users_ID] [int] IDENTITY(1,1) NOT NULL,
[FMOUser_givenName] [nvarchar](max) NULL,
[FMOUser_sn] [nvarchar](max) NULL,
[FMOUser_streetAddress] [nvarchar](max) NULL,
[ExcludeFromMigration] [bit] NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[Users_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
创建链接表的代码:
CREATE TABLE [dbo].[Features](
[Features_ID] [int] IDENTITY(1,1) NOT NULL,
[Feature_Name] [nvarchar](max) NOT NULL
CONSTRAINT [PK_Features] PRIMARY KEY CLUSTERED
(
[Features_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
我已经研究过什么了?
我找到了以下示例:
http://www.dbforums.com/microsoft-sql-server/1673127-view-multiple-records-single-row.html
这确实将新列名称下的多行中的单个列放在一行中,但它不是动态的 - 意味着:它不会从{{1}的相应“功能”行中提取目标列名称}表也不能处理动态数量的CREATE TABLE [dbo].[link_Users__with__Features](
[link_Users__with__Features_ID] [int] IDENTITY(1,1) NOT NULL,
[FMO_Users_ID] [int] NOT NULL,
[Features_Migration_Core_ID] [int] NOT NULL,
[StatusValue] [int] NOT NULL,
[Description] [nvarchar](max) NULL,
CONSTRAINT [PK_link_Users__with__Features] PRIMARY KEY CLUSTERED
(
[link_Users__with__Features_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
。
由于我对T-SQL比较陌生,我失去了如何解决这一挑战。
由于这是我在堆栈溢出时的第一个问题,如果我错过了正式,请原谅我。请纠正我,我会做得更好: - )
提示:我已经提出了我的问题所提议的“重复”,但似乎没有一个甚至与我的问题略有匹配。
答案 0 :(得分:0)
以下代码完成了我在初始问题中所要求的内容:(请注意我已经引入了一个额外的视图:view_Users_ 和 _StatusValues,它们将用户,链接表和功能绑定在一起)
灵感来自:http://www.mssqltips.com/sqlservertip/2783/script-to-create-dynamic-pivot-queries-in-sql-server/
代码:
use [your_database]
-- *** Get the column names for the target 'table' out from the features table
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N',' + QUOTENAME(Feature_Name)
FROM (SELECT p.Feature_Name FROM dbo.Features AS p
INNER JOIN dbo.link_Users__with__Features AS o
ON p.Features_ID = o.Features_ID
GROUP BY p.Feature_Name) AS x;
-- *** remove unneccessary, leading ',' ***
set @columns = STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
-- print @columns
-- *** Create the SQL code which will produce the correct output table ***
SET @sql = N'
select * from dbo.view_FMO_Users__and__StatusValues
pivot(
max(StatusValue) -- use any aggregate function (needed for pivoting)
for Feature_Name in (' + @columns + ')) as FeatureStatusValue'
-- PRINT @sql;
EXEC sp_executesql @sql;
答案 1 :(得分:0)
我个人要注意的问题:如何从透视有意义的名称中给输出列:
(select
Betrieb = [200], IP = [310], port = [311] -- Give friendly names to output columns
from
(select i.INTERFACEID, ioptions.OPTION_IDENTIFIER, ioptions.value from
(tac.I_A_INTERFACE_OPTIONS ioptions join tac.G_M_INTERFACES i on i.INTERFACEID = ioptions.INTERFACEID)
where (OPTION_IDENTIFIER=200 or OPTION_IDENTIFIER=310 or OPTION_IDENTIFIER=311) and i.TYPE = 700)
temp
pivot(
max(value) -- use any aggregate function (needed for pivoting)
for OPTION_IDENTIFIER in (
[310],[311],[200])
) as output
)