2

情况: 3个源表:

1. 用户(包含唯一 ID 和用户特定属性,如firstNamegivenNameStreetAddress等)

2. MigrationFeatures(包含唯一 ID 和Feature_Name

3. Link_Users_and_Features(包含来自Users和的唯一 IDFeatures以及Status列 (int) )

在链接表中,每个用户的行数与Feature表中的行数完全相同,并且这些行中的每一行(每个用户)都链接到一个Feature。每个链接行还包含一个状态值列,该列可以具有不同的值 - 根据Feature特定用户的特定迁移状态。

目标

拥有一个完全动态的查询/SP,它为每个用户返回一行,其中包含Feature该特定用户的每个用户的迁移状态 - 每个迁移状态列都应根据表Feature_Name中对应的Featurefrom命名FeaturesFeature当我在表中添加一个附加项时Feature,不必手动修改所需的查询代码。

提示:该Feature表已经有一个插入触发器,它为每个用户创建这个附加列,并且相关列上存在引用完整性,因此所有用户将始终在链接表中拥有所有对应的行Features

为什么我想要那个:

到目前为止,我只有一个表,其中包含所有用户特定的列 ( Name, givenName, StreetAddress,etc) 以及所有迁移功能状态列 ( SIDhist migrated, homefolder migrated,etc),其中包含所有用户的所有迁移状态数据。

不幸的是,这是完全静态的,每当我添加一个新的时Feature,我都必须修改这个主表。未来,不太熟练的人将使用底层系统,他们不会进入数据库代码或模式,而只会向表Featureuser表中添加记录。

这里是创建用户数据库的代码:

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

创建链接表的代码:

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]

我已经研究了什么?

我找到了以下示例:

http://www.dbforums.com/microsoft-sql-server/1673127-view-multiple-records-single-row.html

这确实将多行中的单列放在新列名下的单行中,但它不是动态的 - 意味着:它不会从Features表中相应的“Feature”行中提取目标列名,也不能处理动态的数量Features

由于我对 T-SQL 比较陌生,我不知道如何解决这个挑战。

由于这是我在堆栈溢出的第一个问题,如果我错过了形式,请原谅我。请纠正我,我会做得更好:-)

提示:我已经查找了针对我的问题提出的“重复”,但似乎没有一个与我的问题稍有匹配。

4

2 回答 2

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;
于 2013-02-17T11:27:08.230 回答
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
)
于 2020-04-14T15:37:21.533 回答