यह काम करेगा, लेकिन चूंकि कोई पहचान या डेटाटाइम कॉलम नहीं है - यह पता लगाने का कोई तरीका नहीं है कि कौन सी अद्यतन पंक्ति नई है। इसलिए यदि एक ही कॉलम पर और अपडेट हैं, तो मैं केवल पहले अक्षर/संख्यात्मक (MIN) को लेता हूं।
WITH CTE AS
(
SELECT ID, REF, MIN(Title) Title, MIN(Surname) Surname, MIN(Forename) Forename, MIN(DOB) DOB, MIN(Add1) Add1, MIN(Postcode) Postcode
FROM Table1
GROUP BY id, REF
)
SELECT
d.REF
, d.ID
, COALESCE(T.Title, d.TItle) AS Title
, COALESCE(T.Surname, d.Surname) AS Surname
, COALESCE(T.Forename, d.Forename) AS Forename
, COALESCE(T.DOB, d.DOB) AS DOB
, COALESCE(T.Add1, d.Add1) AS Add1
, COALESCE(T.Postcode, d.Postcode) AS Postcode
FROM CTE d
INNER JOIN CTE t ON d.ID = t.ID AND d.REF = 'D' AND t.REF = 't'
यदि पहचान कॉलम जोड़ा जा सकता है, तो हम इसे और अधिक सटीक बनाने के लिए सीटीई भाग को फिर से लिख सकते हैं।
संपादित करें:
यदि हमारे पास पहचान कॉलम है, और सीटीई को पुनरावर्ती बनने के लिए फिर से लिखा जाता है, तो वास्तव में क्वेरी के पूरे अन्य भाग को छोड़ा जा सकता है।
WITH CTE_RN AS
(
--Assigning row_Numbers based on identity - it has to be done since identity can always have gaps which would break the recursion
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY IDNT DESC) RN FROM dbo.Table2
)
,RCTE AS
(
SELECT ID ,
Title ,
Surname ,
Forename ,
DOB ,
Add1 ,
Postcode ,
RN FROM CTE_RN WHERE RN = 1 -- taking the last row for each ID
UNION ALL
SELECT r.ID,
COALESCE(r.TItle,p.TItle), --Coalesce will hold prev value if exist or use next one
COALESCE(r.Surname,p.Surname),
COALESCE(r.Forename,p.Forename),
COALESCE(r.DOB,p.DOB),
COALESCE(r.Add1,p.Add1),
COALESCE(r.Postcode,p.Postcode),
p.RN
FROM RCTE r
INNER JOIN CTE_RN p ON r.ID = p.ID AND r.RN + 1 = p.RN --joining the previous row for each id
)
,CTE_Group AS
(
--rcte now holds both merged and unmerged rows, merged is max(rn)
SELECT ID, MAX(RN) RN FROM RCTE
GROUP BY ID
)
SELECT r.* FROM RCTE r
INNER JOIN CTE_Group g ON r.ID = g.ID AND r.RN = g.RN