เหตุใดแบบสอบถาม SQL Server ของฉันจึงทำงานต่างจาก UPDATE มากกว่า SELECT


10

ฉันเขียนแบบสอบถาม SQL Server ที่อัปเดตระเบียนให้มีหมายเลขตามลำดับหลังจากแบ่งพาร์ติชันในเขตข้อมูล เมื่อฉันเรียกใช้เป็นคำสั่ง SELECT ทุกอย่างดูดี:

DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT

SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID

SELECT
    [OrderedRecords].[NewSeq9],
    RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
    (
        SELECT
            [Records].*,
            [Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
        FROM
        (
            SELECT
                [MRDFStorageID], 
                [RunDetailID], 
                [SortField], 
                [PieceID], 
                [Seq9], 
                [BallotType]
            FROM
                [MRDFStorage]
                    JOIN [BallotStyles] ON [MRDFStorage].[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
            WHERE
                [RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID AND [RunStatusID] <> 0)
        ) Records
    ) OrderedRecords 
        JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
    [MRDFStorage].[RunDetailID] = @RunDetailID

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามเมื่อฉันทำแบบสอบถามเป็นคำสั่ง UPDATE มันเริ่มข้ามตัวเลขได้:

DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT 

SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID

UPDATE
    [MRDFStorage]
SET
    [Seq9] = [OrderedRecords].[NewSeq9],
    [Overlay1] = [OrderedRecords].[NewSeq9],
    [Overlay10] = RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
    (
        SELECT
            [Records].*,
            [Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
        FROM
        (
            SELECT
                [MRDFStorageID], 
                [RunDetailID], 
                [SortField], 
                [PieceID], 
                [Seq9], 
                [BallotType], 
                CAST([SpecialProcessing] as Int) StartCount
            FROM
                [MRDFStorage]
                    JOIN [BallotStyles] ON [MRDFStorage].[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
            WHERE
                [RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID AND [RunStatusID] <> 0)
        ) Records
    ) OrderedRecords 
        JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
    [MRDFStorage].[RunDetailID] = @RunDetailID

ป้อนคำอธิบายรูปภาพที่นี่

ฉันได้พยายามเน้นเฉพาะในส่วนนี้:

[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9

มีผลข้างเคียงอะไรบ้างที่ฉันไม่รู้?

อัปเดตพร้อมคำจำกัดความของตาราง

CREATE TABLE [dbo].[MRDFStorage] (
    [MRDFStorageID]           INT            IDENTITY (1, 1) NOT NULL,
    [RunDetailID]             INT            NOT NULL,
    [PieceID]                 VARCHAR (15)   NULL,
    [SortField]               VARCHAR (20)   NULL,
    [BallotType]              VARCHAR (100)  NULL,
    [Seq9]                    VARCHAR (15)   NULL,
    CONSTRAINT [PK_MRDFStorage] PRIMARY KEY CLUSTERED ([MRDFStorageID] ASC),
    CONSTRAINT [FK_MRDFStorage_RunDetails] FOREIGN KEY ([RunDetailID]) REFERENCES [dbo].[RunDetails] ([RunDetailID])
);

CREATE TABLE [dbo].[BallotStyles] (
    [BallotStyleID]     INT           IDENTITY (1, 1) NOT NULL,
    [JobDetailID]       INT           NOT NULL,
    [Style]             VARCHAR (20)  NOT NULL,
    CONSTRAINT [PK_BallotStyles] PRIMARY KEY CLUSTERED ([BallotStyleID] ASC)
);

CREATE TABLE [dbo].[RunDetails] (
    [RunDetailID]        INT            IDENTITY (1, 1) NOT NULL,
    [JobDetailID]        INT            NOT NULL,
    CONSTRAINT [PK_RunDetails] PRIMARY KEY CLUSTERED ([RunDetailID] ASC)
);

2
อืมฉันคิดว่าคุณควรลองแทนที่UPDATE [MRDFStorage]ด้วยUPDATE mและJOIN MRDFStorage ON ...ด้วยJOIN MRDFStorage m ON ...ฉันกลัวว่า UPDATE อาจอัปเดตแถวมากกว่าหนึ่งครั้ง อ่านโพสต์บล็อกนี้: ขอเลิกอัปเดตจาก!
ypercubeᵀᴹ

คำตอบ:


4

ไม่เห็นข้อมูลที่คุณทำให้มันยากขึ้นสักหน่อย แต่ฉันพยายามที่จะทำซ้ำสิ่งที่คุณเห็นถ้าคุณเห็นด้วย:

insert into RunDetails(RunDetailID, JobDetailID) values(448, 1)
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')

ปัจจัยสำคัญที่นี่คือสองแถวBallotStylesค่ะ

คุณจะเข้าร่วมในการในการสอบถามมากที่สุดภายในและมีข้อมูลเช่นข้างต้นคุณจะได้รับแถวที่ซ้ำกันในแต่ละแถวในBallotStyles MRDFStorageเนื่องจากคุณไม่ได้ใช้คอลัมน์ใด ๆ ในตัวBallotStylesคุณกำลังตรวจสอบว่ามีแถวอยู่หรือไม่และสามารถทำได้ด้วยexistsประโยคแทนและแน่นอนว่าจะไม่สร้างแถวที่ซ้ำกัน

UPDATE
    [MRDFStorage]
SET
    [Seq9] = [OrderedRecords].[NewSeq9]
FROM
    (
        SELECT
            MRDFStorageID,
            [Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
        FROM
        (
            SELECT
                M.[MRDFStorageID], 
                M.[RunDetailID], 
                M.[SortField], 
                M.[PieceID], 
                M.[BallotType]
            FROM
                [MRDFStorage] as M
-- Remove this join
--                    JOIN [BallotStyles] ON M.[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
            WHERE
                [RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID) and
-- Add this exists check instead of the join
                EXISTS (
                       SELECT *
                       FROM BallotStyles AS BS
                       WHERE M.SortField = BS.Style and
                             BS.JobDetailID = @JobDetailID
                       )
        ) Records
    ) OrderedRecords 
        JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
    [MRDFStorage].[RunDetailID] = @RunDetailID
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.