问题
I am using SQL Server 2012. I have the following query:
SELECT p.PortfolioGroupID, p.PortfolioGroupCode, p.DisplayOrder, p.MemberCode, m.ContactCode, m.Custom01, 'Separator' As 'PDFType'
FROM [APXFirm].[AdvApp].[vPortfolioGroupMemberFlattened] p
LEFT OUTER JOIN [APXFirm].[AdvApp].[vPortfolioInterestedParty] m
on p.memberid = m.PortfolioID
WHERE m.ContactCode is not null
and p.PortfolioGroupCode like '%_Package'
order by m.ContactCode, p.MemberCode
Current Result Set
PortfolioGroupID PortfolioGroupCode DisplayOrder MemberCode ContactCode Custom01 PDFType
11224 Test1_Package 677 test1 recipient1_ind DVAAnnual Separator
11224 Test1_Package 730 test2 recipient1_ind DVAAnnual Separator
11221 Test2_Package 1825 test3 recipient2_ind DVAAnnual Separator
11221 Test2_Package 1826 test4 recipient2_ind DVAAnnual Separator
11221 Test2_Package 1827 test5 recipient2_ind DVAAnnual Separator
Desired Result Set
PortfolioGroupID PortfolioGroupCode DisplayOrder MemberCode ContactCode Custom01 PDFType
11224 Test1_Package 677 test1 recipient1_ind DVAAnnual Cover
11224 Test1_Package 677 test1 recipient1_ind DVAAnnual Separator
11224 Test1_Package 677 test1 recipient1_ind DVAAnnual Report
11224 Test1_Package 730 test2 recipient1_ind DVAAnnual Separator
11224 Test1_Package 730 test2 recipient1_ind DVAAnnual Report
11221 Test2_Package 1825 test3 recipient2_ind DVAAnnual Cover
11221 Test2_Package 1825 test3 recipient2_ind DVAAnnual Separator
11221 Test2_Package 1825 test3 recipient2_ind DVAAnnual Report
11221 Test2_Package 1826 test4 recipient2_ind DVAAnnual Separator
11221 Test2_Package 1826 test4 recipient2_ind DVAAnnual Report
11221 Test2_Package 1827 test5 recipient2_ind DVAAnnual Separator
11221 Test2_Package 1827 test5 recipient2_ind DVAAnnual Report
For every instance of a group indicated by a new PortfolioGroupID in the PortfolioGroupID column. (In this example there are 2 groups 11224 and 11221) I need one row added as the first row that has the word Cover before where I have placed the word separator. All other columns are identical to the row it is placed before.
For every row in the group I need to interpolate/alternate a row with the word Report after the row where I placed the word separator. All other columns are identical to the row it is placed after.
If for some reason it's easier to place the word Separator before Report I could change the hard-coded value of Separator to Report.
Is this possible?
回答1:
The first step would be to add a RowNumber
column to identify the first row for each PorfoilioGroupID:
SELECT p.PortfolioGroupID,
p.PortfolioGroupCode,
p.DisplayOrder,
p.MemberCode,
m.ContactCode,
m.Custom01,
RowNumber = ROW_NUMBER() OVER(PARTITION BY P.PortfolioGroupID ORDER BY m.ContactCode, p.MemberCode)
FROM [APXFirm].[AdvApp].[vPortfolioGroupMemberFlattened] p
LEFT OUTER JOIN [APXFirm].[AdvApp].[vPortfolioInterestedParty] m
ON p.memberid = m.PortfolioID
WHERE m.ContactCode is not null
AND p.PortfolioGroupCode like '%_Package'
ORDER BY m.ContactCode, p.MemberCode;
Then you can join your results set with a table valued constructor with your 3 values (Cover, Sperator, Report), and just add a where clause to ensure 'Cover' only appears for the first row:
WITH Data AS
( SELECT p.PortfolioGroupID,
p.PortfolioGroupCode,
p.DisplayOrder,
p.MemberCode,
m.ContactCode,
m.Custom01,
RowNumber = ROW_NUMBER() OVER(PARTITION BY P.PortfolioGroupID ORDER BY p.DisplayOrder)
FROM [APXFirm].[AdvApp].[vPortfolioGroupMemberFlattened] p
LEFT OUTER JOIN [APXFirm].[AdvApp].[vPortfolioInterestedParty] m
ON p.memberid = m.PortfolioID
WHERE m.ContactCode is not null
AND p.PortfolioGroupCode like '%_Package'
)
SELECT d.PortfolioGroupID,
d.PortfolioGroupCode,
d.DisplayOrder,
d.MemberCode,
d.ContactCode,
d.Custom01,
t.PDFType
FROM Data d
CROSS JOIN
( VALUES
('Cover'),
('Seperator'),
('Report')
) t (PDFType)
WHERE d.RowNumber = 1
OR t.PDFType != 'Cover'
ORDER BY ContactCode, MemberCode;
Example on SQL Fiddle
来源:https://stackoverflow.com/questions/20763803/dynamically-interpolate-extra-rows-in-sql-query