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 的关系。

我需要查询格式行列表。挑战有几个: + 有一个复合外键。+ 我需要将格式过滤为包含相关字段的子集。+ 相关字段必须与任意数量的过滤条件匹配,然后才能内联到格式。

所以要通过这个:存储过程接收下表值参数:

_FieldDisplayName_  Field_Value
 Field 1             001
 Field 2             002

然后它需要按这些值过滤字段表。

由于我需要使用所有标准,而不仅仅是其中一个,当我不知道我有多少值或 FieldDisplayName 是什么时,我不知道如何使用它来检索有用的加入值将是。

@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)

由于您在 table 参数上使用了内部联接,因此它将根据这些值的配对过滤字段表,并仅返回匹配的字段表的组合键。

于 2012-10-16T22:23:21.763 回答
0
SELECT  a.*, -- select on the rows you want to display by specifying
        b.*  -- their column name instead of using asterisk *
FROM    Formats a
        INNER JOIN Fields b
            ON  a.BatchID = b.BatchID AND
                a.SequenceID = b.SequenceID
于 2012-10-16T22:05:24.490 回答