SQL:如何:根据文件顺序更改字段的值

时间:2013-10-30 17:28:20

标签: sql sql-server

这里的第一次海报......对我来说很容易=)

基本上我要做的是在任何标有“eMail”的记录之后,将标有“附件”的所有记录的[xMedia]列中标记为“attachment”的记录的[attachlvl]更改为“1”。

然后棘手的部分是将[ATTACHPID]更改为附件上方的电子邮件和其下方标记为“附件”的任何内容的唯一编号,我还要填写电子邮件的[附件]字段。由分号分隔的附件的文件名。

这是我的表格:

[docorder]  [docid] [filename]  [attachpid] [attachlvl] [attach]    [xmedia]

1 | SAM003266 | SAM003266^eMailContent.htm | 0 | 0 | NULL | eMail
2 | SAM003268 | SAM003268^eMailContent.htm | 0 | 0 | NULL | eMail
3 | SAM003269 | SAM003269^THEROCKQ12013.pdf | 0 | 0 | NULL | Attachment
4 | SAM003569 | SAM003269^THEROCKQ12014.pdf | 0 | 0 | NULL | Attachment
5 | SAM003270 | SAM003270^eMailContent.htm | 0 | 0 | NULL | eMail
6 | SAM003273 | SAM003273^eMailContent.htm | 0 | 0 | NULL | eMail
7 | SAM003275 | SAM003275^eMailContent.htm | 0 | 0 | NULL | eMail
8 | SAM003276 | SAM003276^fax@washelli.com_20130109_093821.pdf | 0 | 0 | NULL | Attachment
9 | SAM004269 | SAM003269^THEROCKQ12013.pdf | 0 | 0 | NULL | Attachment

这就是我希望最终结果如下所示:

[docorder]  [docid] [filename]  [attachpid] [attachlvl] [attach]    [xmedia]
1 | SAM003266 | SAM003266^eMailContent.htm | 0 | 0 | NULL | eMail
2 | SAM003268 | SAM003268^eMailContent.htm | 1234567 | 0 | SAM003269^THEROCKQ12013.pdf ; SAM003269^THEROCKQ12014.pdf | eMail
3 | SAM003269 | SAM003269^THEROCKQ12013.pdf | 1234567 | 1 | NULL | Attachment
4 | SAM003569 | SAM003269^THEROCKQ12014.pdf | 1234567 | 1 | NULL | Attachment
5 | SAM003270 | SAM003270^eMailContent.htm | 0 | 0 | NULL | eMail
6 | SAM003273 | SAM003273^eMailContent.htm | 0 | 0 | NULL | eMail
7 | SAM003275 | SAM003275^eMailContent.htm | 1234568 | 0 | SAM003276^fax@washelli.com_20130109_093821.pdf ; SAM003269^THEROCKQ12013.pdf | eMail
8 | SAM003276 | SAM003276^fax@washelli.com_20130109_093821.pdf | 1234568 | 1 | NULL | Attachment
9 | SAM004269 | SAM003269^THEROCKQ12013.pdf | 1234568 | 1 | NULL | Attachment

1 个答案:

答案 0 :(得分:2)

如果你进行了规范化,这将更容易,这是下面的查询所做的公平讨论。

DECLARE @t TABLE 
(
    [docorder] INT, 
    [docid] VARCHAR(20),
    [filename] VARCHAR(100),
    [attachpid] INT,
    [attachlvl] INT,
    [attach] VARCHAR(MAX),
    [xmedia] VARCHAR(20)
)

INSERT INTO @t ([docorder],[docid],[filename],[attachpid],[attachlvl],[attach],[xmedia])
VALUES
    (1 , 'SAM003266' , 'SAM003266^eMailContent.htm' , 0 , 0 , NULL , 'eMail'),
    (2 , 'SAM003268' , 'SAM003268^eMailContent.htm' , 0 , 0 , NULL , 'eMail'),
    (3 , 'SAM003269' , 'SAM003269^THEROCKQ12013.pdf' , 0 , 0 , NULL , 'Attachment'),
    (4 , 'SAM003569' , 'SAM003269^THEROCKQ12014.pdf' , 0 , 0 , NULL , 'Attachment'),
    (5 , 'SAM003270' , 'SAM003270^eMailContent.htm' , 0 , 0 , NULL , 'eMail'),
    (6 , 'SAM003273' , 'SAM003273^eMailContent.htm' , 0 , 0 , NULL , 'eMail'),
    (7 , 'SAM003275' , 'SAM003275^eMailContent.htm' , 0 , 0 , NULL , 'eMail'),
    (8 , 'SAM003276' , 'SAM003276^fax@washelli.com_20130109_093821.pdf' , 0 , 0 , NULL , 'Attachment'),
    (9 , 'SAM004269' , 'SAM003269^THEROCKQ12013.pdf' , 0 , 0 , NULL , 'Attachment')

;WITH emails AS
(
    SELECT 
        emails.docorder, 
        emails.docid, 
        emails.[filename], 
        CHECKSUM(emails.[docid]) emailpid,
        attachpid,
        emails.attachlvl,
        emails.[attach], 
        emails.xmedia
    FROM @t emails WHERE emails.xmedia='email'
)
, attachments AS
(
    SELECT *
    FROM (
        SELECT 
            attachments.docorder, 
            attachments.docid, 
            attachments.[filename], 
            CHECKSUM(emails.[docid]) emailpid,
            1 attachlvl, 
            attachments.[attach], 
            attachments.xmedia, 
            DENSE_RANK() OVER (PARTITION BY attachments.docid ORDER BY emails.docorder DESC) dr
        FROM emails
        JOIN (
            SELECT * FROM @t WHERE xmedia='attachment'
        ) attachments ON attachments.docorder > emails.docorder
    ) t
    WHERE dr=1
)
, grouped_attachments AS
(
    SELECT emailpid, LEFT(filenames , LEN(filenames )-1) filenames
    FROM attachments AS extern
    CROSS APPLY
    (
        SELECT [filename] + ';'
        FROM attachments AS intern
        WHERE extern.emailpid = intern.emailpid
        FOR XML PATH('')
    ) pre_trimmed (filenames)
    GROUP BY emailpid, filenames
)
SELECT 
    emails.docorder, 
    emails.docid, 
    emails.[filename], 
    COALESCE(grouped_attachments.emailpid, emails.attachpid) attachpid,
    emails.attachlvl, 
    grouped_attachments.filenames [attach], 
    emails.xmedia
FROM emails
LEFT JOIN grouped_attachments ON grouped_attachments.emailpid = emails.emailpid
UNION ALL
SELECT 
    attachments.docorder, 
    attachments.docid, 
    attachments.[filename], 
    grouped_attachments.emailpid attachpid,
    attachments.attachlvl, 
    attachments.[attach], 
    attachments.xmedia
FROM attachments
LEFT JOIN grouped_attachments ON grouped_attachments.emailpid = attachments.emailpid
ORDER BY docorder

sqlfiddle