2

状況: 3 つのソース テーブル:

1. ユーザーfirstName(一意の ID と、givenName、などのユーザー固有のプロパティを含むStreetAddress)

2. MigrationFeatures (一意の ID と を含むFeature_Name)

3. Link_Users_and_Features ( と の一意の ID と列 (int) の両方Usersを含むFeatures)Status

リンク テーブルでは、ユーザーごとに、Featureテーブル内の行と同じ数の行があり、これらの各行 (ユーザーごと) は正確に 1 つの にリンクされていますFeature。各リンク行には、特定のユーザーの特定の移行ステータスに応じて、異なる値を持つステータス値列も含まれFeatureます。

目標

ユーザーごとに 1 つの行を返し、その特定のユーザーのそれぞれの移行ステータスを含む完全に動的なクエリ/SP を持つ- 各移行ステータス列は、対応するテーブルのFeature名前に従って命名する必要があります。テーブルに追加する場合、目的のクエリ コードを手動で変更する必要はありません。Feature_NameFeatureFeaturesFeatureFeature

ヒント:Featureテーブルには、ユーザーごとにこの追加の列を作成する挿入トリガーが既にあり、関連する列に参照整合性があるため、すべてのユーザーは常にすべてのリンク テーブルに対応するすべての行を持ちますFeatures

なぜ私はそれを持ちたいのですか:

これまで、すべてのユーザー固有の列 (Name, givenName, StreetAddress,など) とすべての移行機能ステータス列 (SIDhist migrated, homefolder migrated,など) を含む 1 つのテーブルがあり、すべてのユーザーのすべての移行ステータス データが保持されていました。

残念ながら、これは完全に静的であり、新しい を追加するたびに、Featureこのマスター テーブルを変更する必要があります。Feature将来的には、スキルの低い人が基礎となるシステムを使用し、DB コードやスキーマにはアクセスせず、およびuserテーブルにレコードを追加するだけになるでしょう。

ユーザーDBを作成するコードは次のとおりです。

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

Features テーブルを作成するコードは次のとおりです。

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]

私はすでに何をrResearchしましたか?

次の例を見つけました。

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

Featuresこれは、複数の行から単一の列を新しい列名の下に1つの行に配置しますが、動的ではありません-つまり、テーブルの対応する「機能」行からターゲット列名を引き出さず、動的を処理することもできませんの数Features

私はT-SQLに比較的慣れていないので、この課題を解決する方法がわかりません。

これはスタック オーバーフローでの私の最初の質問なので、形式を逃した場合はご容赦ください。私を修正してください。私はもっとうまくやります:-)

ヒント: 私は自分の質問に対して提案された「重複」を調べましたが、私の質問に少しでも一致するものはないようです。

4

2 に答える 2

0

次のコードは、最初の質問で必要なことを実行します: (追加のビューを導入したことに注意してください: view_Users_および_StatusValues は、Users、リンク テーブル、および機能を結び付けます)

これは、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 に答える