我说这个问题的原始方式对大多数人来说都没有用,所以我对它进行了大量修改。
我有一个遗留数据库,其架构我无法控制(也从未有过)。 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
格式:字段之间存在1:许多关系。
我需要查询格式行列表。挑战有几个: +有一个复合外键。 +我需要将格式过滤到包含相关字段的子集。 +在内部连接到格式之前,相关字段必须匹配任意数量的过滤条件。
所以要走过这个: 存储过程接收以下表值参数:
_FieldDisplayName_ Field_Value
Field 1 001
Field 2 002
然后需要按这些值过滤Fields表。
由于我需要使用所有标准,而不仅仅是其中一个,我不知道如何使用它来检索有用的东西,当我不知道我有多少值时,或者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)
答案 0 :(得分: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
答案 1 :(得分: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参数上使用内连接,它将根据这些值的配对过滤字段表,并仅返回匹配的Fields表的组合键。