0

この質問の元の言い方はほとんどの人にとって役に立たないので、大幅に作り直しました。

私はレガシーデータベースを持っていますが、そのスキーマを制御することはできません (制御したこともありません)。db スキーマは、アンマネージ C++ で使用するためにプロバイダーに依存しないように設計されているため、FK 制約などはありません。.NET からこれを使用する必要があり、当初の意図とは大きく異なるデータを提示する必要もあります。 .

関連するテーブルのスキーマは次のとおりです(この質問のキーの量を太字/アスタリスクで囲みました):

CREATE TABLE [dbo].[Formats](
[GroupName] [varchar](255) NOT NULL,
**[BatchID] [bigint] NOT NULL,**
[SeriesNumber] [bigint] NOT NULL,
**[SequenceID] [bigint] NOT NULL,**
[SeqNum] [int] NOT NULL,
[FormatName] [varchar](50) NOT NULL

CREATE TABLE [dbo].[Fields](
[GroupName] [varchar](255) NOT NULL,
**[BatchID] [bigint] NOT NULL,**
**[SequenceID] [bigint] NOT NULL,**
[SeqNum] [int] NOT NULL,
**[FieldName] [varchar](50) NOT NULL,**
[FieldDisplayName] [varchar](50) NOT NULL,
[FieldValue] [ntext] NULL

Formats:Fields の間には 1:Many の関係があります。

フォーマット行のリストを照会する必要があります。課題はいくつかあります: + 複合外部キーがあります。+ 関連するフィールドを含むサブセットにフォーマットをフィルタリングする必要があります。+ 関連するフィールドは、フォーマットに内部結合される前に、任意の数のフィルター条件に一致する必要があります。

Stored Proc は、次のテーブル値パラメーターを受け取ります。

_FieldDisplayName_  Field_Value
 Field 1             001
 Field 2             002

次に、これらの値で Fields テーブルをフィルター処理する必要があります。

基準の 1 つだけでなく、すべての基準を使用する必要があったため、これを使用して結合に役立つものを取得する方法がわかりませんでした。値になります。

@Joe Phillips は、混乱を見抜くのに十分賢く、テーブルをピボットする必要があることを示唆しました。それはこれです:

編集: 以下はデータをピボットするために機能していますが、それが理想的かどうかはわかりません。答えを提供する前に、まだ他のアイデアを待っています。

TVP を使用する代わりに、一時テーブルと動的 SQL を使用しています (もちろん、インジェクションの脆弱性も見られます)。

IF OBJECT_ID('[tempdb].[dbo].[#FilterFields]') is not null
Drop Table dbo.#FilterFields

CREATE Table #FilterFields (FieldDisplayName varchar(50), FieldValue nvarchar(max))
/* Just some example data */
INSERT INTO #FilterFields (FieldDisplayName, FieldValue) VALUES ('PTNUM', '011')
INSERT INTO #FilterFields (FieldDisplayName, FieldValue) VALUES('SITENUM', '001')

Declare @column_names varchar(max)
Declare @dynamic_pivot_query as varchar(max)

SELECT @column_names = Stuff((SELECT DISTINCT ',[' + FieldDisplayName + ']'
                FROM #FilterFields FOR xml path('')),1,1,'')

PRINT(@column_names)    

SET @dynamic_pivot_query =
'select * ' +
'from tempdb.dbo.#FilterFields ' +
'Pivot
(
MIN(
    FieldValue
    )
FOR FieldDisplayName IN (' + @column_names + ')
) as P'

PRINT(@dynamic_pivot_query)
EXEC(@dynamic_pivot_query)
4

2 に答える 2

0

値のリストを持つ複合キーを (機能的に) 持っているため、副選択で IN を活用する必要があります。これを行うには、フィールドを結合する必要があります。これは、キー ペアごとに一意になるように結合する必要があるため、可能性のあるデータについて少なくとも少し知っていることを意味します。BatchID と SequenceID が設定された長さの文字列である場合は、おそらくそれらを追加するだけで十分です。それらが異なる場合は、ダッシュやアンパサンドのように表示されない区切り記号が必要になる場合があります。ここでデモンストレーションします。

SELECT  *
FROM    Formats format 
WHERE   format.BatchID + '-' + format.SequenceID  IN 
    (SELECT field.BatchID + '-' + field.SequenceID
     FROM Fields field
           INNER JOIN #FilterFields filter
               ON filter.FieldDisplayName = field.FieldDisplayName AND
                  filter.FieldValue = field.FieldValue)

テーブル パラメーターで内部結合を使用しているため、これらの値のペアに基づいてフィールド テーブルがフィルター処理され、一致するフィールド テーブルの結合キーのみが返されます。

于 2012-10-16T22:23:21.763 に答える