Sai*_*udo 10 pivot t-sql sql-server-2012
我重新组织了数据库中的一些表以使其更加灵活,但我不确定如何编写 SQL 以从中提取有意义的数据。
我有以下表格(为了更清楚的例子,有些缩写):
CREATE TABLE Loans(
Id int,
SchemaId int,
LoanNumber nvarchar(100)
);
CREATE TABLE SchemaFields(
Id int,
SchemaId int,
FieldName nvarchar(255)
);
CREATE TABLE LoanFields(
Id int,
LoanId int,
SchemaFieldId int,
FieldValue nvarchar(4000)
);
Run Code Online (Sandbox Code Playgroud)
使用以下数据:
INSERT INTO Loans (Id, SchemaId, LoanNumber) VALUES (1, 1, 'ABC123');
INSERT INTO SchemaFields (Id, SchemaId, FieldName) VALUES (1, 1, 'First Name');
INSERT INTO SchemaFields (Id, SchemaId, FieldName) VALUES (2, 1, 'Last Name');
INSERT INTO LoanFields (Id, LoanId, SchemaFieldId, FieldValue) VALUES (1, 1, 1, 'John');
INSERT INTO LoanFields (Id, LoanId, SchemaFieldId, FieldValue) VALUES (2, 1, 2, 'Doe');
Run Code Online (Sandbox Code Playgroud)
目标是获得一个查询,该查询对于所有字段的贷款都是平坦的。(在现实世界中,同一个模式可能有 20-30 个字段,但我们在示例中只有 2 个):
LoanNumber First Name Last Name
---------- ----------- ----------
ABC123 John Doe
Run Code Online (Sandbox Code Playgroud)
我不能使用引用“名字”和“姓氏”的数据透视表,因为我不知道那里实际存在什么。
我这里有一个SQL Fiddle,其中的架构已经就位。
我怎样才能得到想要的结果?
这可以使用PIVOT函数来完成,但由于听起来您想根据 schemaId 更改查询,那么您将需要使用动态 SQL。
如果您有已知数量的值或知道特定 schemaID 的列,那么您可以对查询进行硬编码。静态查询将是:
select loannumber,
[First Name],
[Middle Name],
[Last Name]
from
(
select
l.loannumber,
sf.fieldname,
lf.fieldvalue
from loans l
left join loanfields lf
on l.id = lf.loanid
left join schemafields sf
on lf.schemafieldid = sf.id
and l.schemaid = sf.schemaid
) src
pivot
(
max(fieldvalue)
for fieldname in ([First Name], [Middle Name], [Last Name])
)piv;
Run Code Online (Sandbox Code Playgroud)
如果您有一个未知数字,或者您希望根据SchemaId
您传递给过程的a 来更改列,那么您将使用动态 SQL 来生成 SQL 字符串:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@schemaId int = 1
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(FieldName)
from SchemaFields
where schemaid = @schemaid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT loannumber,' + @cols + '
from
(
select
l.loannumber,
sf.fieldname,
lf.fieldvalue
from loans l
left join loanfields lf
on l.id = lf.loanid
left join schemafields sf
on lf.schemafieldid = sf.id
and l.schemaid = sf.schemaid
where sf.schemaid = '+cast(@schemaid as varchar(10))+'
) x
pivot
(
max(fieldvalue)
for fieldname in (' + @cols + ')
) p '
execute(@query);
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。这两个查询都会生成结果:
| LOANNUMBER | FIRST NAME | LAST NAME | MIDDLE NAME |
-----------------------------------------------------
| ABC123 | John | Doe | (null) |
| XYZ789 | Charles | Smith | Lee |
Run Code Online (Sandbox Code Playgroud)