අනුපිටපත් පේළි ඉවත් කරන්නේ කෙසේද?


1289

තරමක් විශාල SQL Serverවගුවකින් (එනම් 300,000+ පේළි) අනුපිටපත් පේළි ඉවත් කිරීමට හොඳම ක්‍රමය කුමක්ද?

RowIDඅනන්‍යතා ක්‍ෂේත්‍රයේ පැවැත්ම නිසා පේළි පරිපූර්ණ අනුපිටපත් නොවනු ඇත .

MyTable

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

13
මෙය කියවන PostgreSQL පරිශීලකයන් (ගොඩක්, එය සම්බන්ධ වන ආකාරය බොහෝ විට යන්නේ) සඳහා ඉක්මන් ඉඟිය: ඔබට නොහැක එසේ pg updatable අදහස් ලෙස CTE කොන්දේසි එලිදරව් කරන්නේ නැත DELETE FROMවූ CTE කාලීන සෘජුවම. Stackoverflow.com/q/18439054/398670
ක්‍රේග් රින්ගර්

@CraigRinger ඒ සඳහා සැබෑ ය සයිබේස් - මම මෙතන ඉතිරි විසඳුම් එකතු කර ඇත (ද, පී.ජී. සහ වෙනත් අය සඳහා වලංගු විය යුතුය: stackoverflow.com/q/19544489/1855801 (පමණක් වෙනුවට ROWID()ඕනෑම නම්, RowID තීරුව විසින් කාර්යය)
maf-soft

12
මෙහි අවවාදයක් එක් කිරීමට පමණි. කිසියම් අනුපිටපත් කිරීමේ ක්‍රියාවලියක් ක්‍රියාත්මක කරන විට, ඔබ මුලින් මකාදමන්නේ කුමක්දැයි දෙවරක් පරීක්ෂා කරන්න! හොඳ දත්ත අහම්බෙන් මකා දැමීම ඉතා සුලභ වන එවැනි අංශවලින් එකකි.
ජෙෆ් ඩේවිස්

Answers:


1145

කිසිදු nulls උපකල්පනය, ඔබ GROUP BYසුවිශේෂී තීර සහ SELECTඑම MIN (or MAX)තබා ගැනීමට පේළිය ලෙස RowId. පසුව, පේළි හැඳුනුම්පතක් නොමැති සියල්ල මකන්න:

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

ඔබට පූර්ණ සංඛ්‍යාවක් වෙනුවට GUID එකක් තිබේ නම්, ඔබට එය ප්‍රතිස්ථාපනය කළ හැකිය

MIN(RowId)

සමග

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

330
මෙයද ක්‍රියාත්මක වේද? DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
ජෝර්ජ් ෂෝලි

10
Nd ඇන්ඩ්‍රි - SQL සේවාදායකයේ sqlinthewild.co.za/index.php/2010/03/23/LEFT JOIN ට වඩා අඩු කාර්යක්ෂමතාවයක් NOT EXISTS ඇත . එම වෙබ් අඩවියමNOT IN එදිරිව එදිරිව සංසන්දනය කරයි NOT EXISTS. sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in 3 න් 3 ක්මNOT EXISTS හොඳම දේ කරයි. මෙම තිදෙනාම ස්වයං සම්බන්ධතාවයකින් සැලැස්මක් ජනනය කරනු ඇත.
මාටින් ස්මිත්

12
Ar මාටින්, e ජෝර්ජ්: ඉතින්, මම කුඩා පරීක්ෂණයක් කළා. මෙහි විස්තර කර ඇති පරිදි විශාල වගුවක් නිර්මාණය කර ජනගහනය කර ඇත: sqlinthewild.co.za/index.php/2010/03/23/… පසුව තෝරාගත් දෙකක් නිෂ්පාදනය කරන ලදී, එකක් LEFT JOIN + WHERE IS NULL තාක්‍ෂණය භාවිතා කරන අතර අනෙක NOT භාවිතා කරයි එකක් තුළ. ඉන්පසු මම ක්‍රියාත්මක කිරීමේ සැලසුම් සමඟ ඉදිරියට ගියෙමි. විමසුම හා වියදම් නො, සඳහා 82% එරෙහිව වම් සඳහා 18% එකතු වන්න ලදී විශාල මට පුදුමයක්. මා විසින් නොකළ යුතු දෙයක් හෝ ඊට වෙනස්ව මම කර ඇති අතර, එය සත්‍ය නම් මම දැන ගැනීමට කැමතියි.
ඇන්ඩ්‍රි එම්

16
@ ජෝර්ජ්ෂාලි විසින් අලංකාර පිළිතුරක් ලබා දී ඇත. මගේ PHP දෝෂයක් අනුපිටපත් පේළි නිර්මාණය කළ මේසයක් මත මම එය භාවිතා කර ඇත්තෙමි.
පිලිප් කර්න්ස්

12
කණගාටුයි නමුත් DELETE MyTable FROM MyTableනිවැරදි වාක්‍ය ඛණ්ඩය වන්නේ ඇයි ? මෙහිDELETE ඇති ලේඛනයේ විකල්පයක් ලෙස වගුවේ නම තැබීමෙන් මා දකින්නේ නැත . මෙය අන් අයට පැහැදිලිව පෙනේ නම් කණගාටුයි; මම ඉගෙනීමට උත්සාහ කරන SQL වෙත නවකයෙක් වෙමි. වඩා වැදගත් වන්නේ එය ක්‍රියාත්මක වන්නේ මන්ද යන්නයි: එහි වගුවේ නම ඇතුළත් කිරීම හෝ නොකිරීම අතර වෙනස කුමක්ද?
levininja

761

මෙය කළ හැකි තවත් ක්‍රමයක් නම්

; 

--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1;

මා ORDER BY (SELECT 0)ඉහත භාවිතා කරන්නේ ටයි පටියකදී ආරක්ෂා කර ගත යුතු පේළිය අත්තනෝමතික බැවිනි.

RowIDඋදාහරණයක් ලෙස ඔබට භාවිතා කළ හැකි නවතම දේ සංරක්ෂණය කිරීමORDER BY RowID DESC

ක්‍රියාත්මක කිරීමේ සැලසුම්

මේ සඳහා ක්‍රියාත්මක කිරීමේ සැලැස්ම බොහෝ විට පිළිගත් පිළිතුරට වඩා සරල හා කාර්යක්ෂම වන්නේ එයට ස්වයං සම්බන්ධ වීම අවශ්‍ය නොවන බැවිනි.

ක්‍රියාත්මක කිරීමේ සැලසුම්

කෙසේ වෙතත් මෙය සැමවිටම එසේ නොවේ. GROUP BYවිසඳුමට වැඩි කැමැත්තක් දැක්විය හැකි එක් ස්ථානයක් වන්නේ ධාරා සමස්ථයකට වඩා හැෂ් එකතුවක් තෝරා ගැනීමයි.

මෙම ROW_NUMBERවන ෙහයින් ද විසඳුමක් සෑම විටම එකම සැලැස්මක් එච්චරමයි දෙනවා GROUP BYඋපාය වඩාත් නම්යශීලී වේ.

ක්‍රියාත්මක කිරීමේ සැලසුම්

හැෂ් සමස්ථ ප්‍රවේශයට හිතකර සාධක වනු ඇත

  • කොටස් කිරීමේ තීරුවල ප්‍රයෝජනවත් දර්ශකයක් නොමැත
  • එක් එක් කාණ්ඩයේ සාපේක්ෂව වැඩි අනුපිටපත් ඇති සාපේක්ෂව අඩු කණ්ඩායම්

මෙම දෙවන නඩුවේ ආන්තික අනුවාද වලදී (එක් එක් අනුපිටපත් සහිත කණ්ඩායම් ඉතා ස්වල්පයක් තිබේ නම්) යමෙකුට නව වගුවක තබා ගැනීම සඳහා පේළි ඇතුළත් කිරීම ගැන සලකා බැලිය හැකිය - ඉන්පසු TRUNCATEමුල් පිටපත මකාදැමීමට සාපේක්ෂව ලොග් වීම අවම කිරීම සඳහා ඒවා නැවත පිටපත් කිරීම. පේළි ඉතා ඉහළ අනුපාතය.


28
මා එකතු කළහොත්: පිළිගත් පිළිතුර භාවිතා කරන වගු සමඟ ක්‍රියා නොකරයි uniqueidentifier. මෙය වඩාත් සරල වන අතර ඕනෑම මේසයක් මත පරිපූර්ණව ක්‍රියා කරයි. ස්තූතියි මාටින්.
බ un නෝ එල්එම්

15
මෙය එතරම් පුදුමාකාර පිළිතුරකි! එහි අනුපිටපත් ඇති බව වටහා ගැනීමට පෙර මම පැරණි පී.කේ. ඉවත් කළ විට එය ක්‍රියාත්මක විය. +100
මයිකල් එලියාසන්

12
DBA.SE හි මෙම ප්‍රශ්නය (මෙම පිළිතුර සමඟ) විමසීමට සහ පිළිතුරු දීමට මම යෝජනා කරමි. එවිට අපට එය අපගේ කැනොනිකල් පිළිතුරු ලැයිස්තුවට එකතු කළ හැකිය .
නික් චම්මාස්

16
පිළිගත් පිළිතුර මෙන් නොව, මෙය RowIdසැසඳීමට යතුරක් නොමැති මේසයක් මත ද ක්‍රියා කළේය .
vossad01

8
මෙය සියලුම SQL සේවාදායක අනුවාද වල ක්‍රියා නොකරයි, අනෙක් අතට
ඩේවිඩ්

151

මයික්‍රොසොෆ්ට් ආධාරක අඩවියේ අනුපිටපත් ඉවත් කිරීම පිළිබඳ හොඳ ලිපියක් තිබේ . එය ඉතා ගතානුගතිකයි - ඔවුන් ඔබට සෑම දෙයක්ම වෙන වෙනම පියවරෙන් පියවර කර ඇත - නමුත් එය විශාල වගු වලට එරෙහිව හොඳින් ක්‍රියා කළ යුතුය.

අතීතයේ දී මෙය සිදු කිරීම සඳහා මම ස්වයං-සම්බන්ධතා භාවිතා කර ඇත්තෙමි, එය බොහෝ විට එය සහිත වගන්තියක් සමඟ මවාපෑමට ඉඩ ඇත:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField

පරිපූර්ණ! මගේ පැරණි mariadb අනුවාදය 10.1.xx හි අනුපිටපත් පේළි ඉවත් කිරීමට වඩාත්ම කාර්යක්ෂම ක්‍රමය මෙය බව මට පෙනී ගියේය. ඔබට ස්තුතියි!
බේබදු එම්

තේරුම් ගැනීමට වඩා සරල හා පහසුය!
මාක්

98

අනුපිටපත් පේළි මකා දැමීමට පහත විමසුම ප්‍රයෝජනවත් වේ. මෙම උදාහරණයේ ඇති වගුවේ IDඅනන්‍යතා තීරුවක් ඇති අතර අනුපිටපත් දත්ත ඇති තීරු Column1, Column2සහ Column3.

DELETE FROM TableName
WHERE  ID NOT IN (SELECT MAX(ID)
                  FROM   TableName
                  GROUP  BY Column1,
                            Column2,
                            Column3
                  /*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
                    nullable. Because of semantics of NOT IN (NULL) including the clause
                    below can simplify the plan*/
                  HAVING MAX(ID) IS NOT NULL) 

පහත සඳහන් කේත රචනය දර්ශන භාවිතය GROUP BY, HAVING, ORDER BYඑක් විමසුම, සහ අනුපිටපත් තීරු හා එහි ගණන් සමග ප්රතිඵල පැමිණේ.

SELECT YourColumnName,
       COUNT(*) TotalCount
FROM   YourTableName
GROUP  BY YourColumnName
HAVING COUNT(*) > 1
ORDER  BY COUNT(*) DESC 

1
පළමු ස්ක්‍රිප්ටයේ ඇති MySQL දෝෂය 'FROM වගන්තියේ යාවත්කාලීන කිරීම සඳහා ඔබට ඉලක්ක වගුව' TableName 'නියම කළ නොහැක'
D.Rosado

D.Rosado දැනටමත් වාර්තා කර ඇති දෝෂයට අමතරව, ඔබේ පළමු විමසුම ද ඉතා මන්දගාමී ය. අනුරූපී SELECT විමසුම මගේ සැකසුම + - පිළිගත් පිළිතුරට වඩා 20 ගුණයක් දිගු විය.
parvus

8
arparvus - ප්‍රශ්නය ටැග් කර ඇත්තේ SQL සේවාදායකය MySQL නොවේ. SQL සේවාදායකයේ සින්ටැක්ස් හොඳයි. ද MySQL විමසුම් උප, උපරිම ප්රතිලාභ ලබා දී අපකීර්තිමත් නරක මෙහි උදාහරණයක් බලන්න . මෙම පිළිතුර SQL සේවාදායකයේ හොඳයි. ඇත්ත වශයෙන්ම NOT INබොහෝ විට වඩා හොඳින් ක්රියා කරයි OUTER JOIN ... NULL. HAVING MAX(ID) IS NOT NULLඅර්ථ නිරූපණය අවශ්‍ය නොවුවද, මෙහි සැලසුම් උදාහරණය
මාටින් ස්මිත්

2
PostgreSQL 8.4 හි විශිෂ්ට ලෙස ක්‍රියා කරයි.
උතුරු

63
delete t1
from table t1, table t2
where t1.columnA = t2.columnA
and t1.rowid>t2.rowid

Postgres:

delete
from table t1
using table t2
where t1.columnA = t2.columnA
and t1.rowid > t2.rowid

SQL සේවාදායක ප්‍රශ්නයකට Postgres විසඳුමක් පළ කරන්නේ ඇයි?
ලන්කිමාර්ට්

2
Ng ලන්කිමාර්ට් නිසා පෝස්ට්ග්‍රෙස් භාවිතා කරන්නන් මෙහි පැමිණේ. මෙම පිළිතුරේ ලකුණු දෙස බලන්න.
ගේබ්‍රියෙල්

2
මම මේ සමහර ප්රසිද්ධ SQL ප්රශ්න දී මෙන්, දැකලා තියෙනවා මෙතන , මෙතන හා මෙතන . OP ට ඔහුගේ පිළිතුර ලැබුණු අතර අනෙක් සියල්ලන්ටම යම් උපකාරයක් ලැබුණි. IMHO ගැටළුවක් නැත.
ගේබ්‍රියෙල්

44
DELETE LU 
FROM   (SELECT *, 
               Row_number() 
                 OVER ( 
                   partition BY col1, col1, col3 
                   ORDER BY rowid DESC) [Row] 
        FROM   mytable) LU 
WHERE  [row] > 1 

1
මට මෙම පණිවිඩය දුඹුරු පැහැයෙන් ලබා ගත හැකිය SQL DW: DELETE ප්‍රකාශයක FROM වගන්තියක් දැනට සහය නොදක්වයි.
අමිත්

40

මෙය පළමු පේළිය හැර අනුපිටපත් පේළි මකා දමනු ඇත

DELETE
FROM
    Mytable
WHERE
    RowID NOT IN (
        SELECT
            MIN(RowID)
        FROM
            Mytable
        GROUP BY
            Col1,
            Col2,
            Col3
    )

බලන්න ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )


10
MySQL සඳහා එය දෝෂයක් ලබා දෙනු ඇත: දෝෂ කේතය: 1093. FROM වගන්තියේ යාවත්කාලීන කිරීම සඳහා ඔබට ඉලක්කගත වගුව 'Mytable' නියම කළ නොහැක. කොතැනින්ද RowID නො ((සිෙලක්ට් ස ෙදන (RowID) ලෙස හැඳුනුම්පත Mytable පිරිසක් විසින් Col1, Col2, Col3) සිට Temp පරිදි තෝරා ID) Mytable වලින් මකන්න: නමුත් මේ කුඩා වෙනසක් MySQL සඳහා කටයුතු කරනු ඇත
Ritesh

35

SQL සේවාදායක වගුවෙන් අනුපිටපත් පේළි මකා දැමීමට මම CTE ට කැමතියි

මෙම ලිපිය අනුගමනය කිරීමට තරයේ නිර්දේශ කරමු :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/

මුල් පිටපත තබා ගැනීමෙන්

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1

මුල් පිටපත් නොකර

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)

25

අනුපිටපත් පේළි ලබා ගැනීමට:

SELECT
name, email, COUNT(*)
FROM 
users
GROUP BY
name, email
HAVING COUNT(*) > 1

අනුපිටපත් පේළි මකා දැමීමට:

DELETE users 
WHERE rowid NOT IN 
(SELECT MIN(rowid)
FROM users
GROUP BY name, email);      

MySQL භාවිතා කරන්නන් සඳහා, පළමුව එය විය යුතු බව සලකන්න DELETE FROM, දෙවනුව, එය ක්‍රියා නොකරනු ඇත, මන්ද ඔබ SELECTඇතුළු වන එකම වගුවෙන් ඔබට එය කළ නොහැකි බැවිනි DELETE. MySQL හි මෙය පුපුරා යයි MySQL error 1093.
Íhor Mé

23

නිශ්චිත අනුපිටපත් පේළි මකා දැමීමට ඉක්මන් හා අපිරිසිදු (කුඩා වගු සඳහා):

select  distinct * into t2 from t1;
delete from t1;
insert into t1 select *  from t2;
drop table t2;

3
ප්‍රශ්නය ඇත්ත වශයෙන්ම නිශ්චිත නොවන අනුපිටපත් (dueto row id) නියම කරන බව සලකන්න.
ඩෙනිස් ජහරුදින්

21

කියවීමට පහසු බව මට පෙනී ගිය හෙයින්, ඔබ එය ක්‍රියාත්මක කිරීමට පෙර මකා දැමිය යුතු දේ සත්‍යාපනය කිරීම සඳහා තෝරාගත් ප්‍රකාශයක් බවට පත් කිරීම ඉතා පහසු බැවින්, අභ්‍යන්තර සම්බන්ධතාවයට විසඳුමක් (*)> 1 විසඳුමට මම කැමැත්තෙමි.

--DELETE FROM table1 
--WHERE id IN ( 
     SELECT MIN(id) FROM table1 
     GROUP BY col1, col2, col3 
     -- could add a WHERE clause here to further filter
     HAVING count(*) > 1
--)

අභ්‍යන්තර විමසුමේ පෙන්වන සියලුම වාර්තා මකා නොදමන්නේද? අපට අවශ්‍ය වන්නේ අනුපිටපත් පමණක් ඉවත් කර මුල් පිටපත ආරක්ෂා කිරීමයි.
සැන්ඩි

3
තෝරාගත් වගන්තියේ මිනි (හැඳුනුම්පත) මත පදනම්ව ඔබ අඩුම හැඳුනුම්පත සහිත එකක් පමණක් ආපසු එවයි.
ජේම්ස් එරිකෝ

2
විමසුමේ පළමු, දෙවන සහ අවසාන පේළි ඉවත් කරන්න.
ජේම්ස් එරිකෝ

7
මෙය සියලු අනුපිටපත් පිරිසිදු නොකරයි. ඔබට අනුපිටපත් පේළි 3 ක් තිබේ නම්, එය පේළිය තෝරා ගන්නේ MIN (id) සමඟ පමණක් වන අතර, එය මකා දමනු ඇත, අනුපිටපත් පේළි දෙකක් ඉතිරි වේ.
ක්ලෝයි

2
එසේ වුවද, මම මෙම ප්‍රකාශය නැවත නැවතත් පුනරාවර්තනය කර අවසන් කළෙමි, එමඟින් සම්බන්ධතාවය කල් ඉකුත්වීම හෝ පරිගණකය නින්දට යාම වෙනුවට ප්‍රගතියක් ලැබෙනු ඇත. MAX(id)පසු අනුපිටපත් තුරන් කිරීම සඳහා මම එය වෙනස් කර LIMIT 1000000අභ්‍යන්තර විමසුමට එකතු කළෙමි , එවිට එය මුළු වගුව පරිලෝකනය කළ යුතු නොවේ. මෙය අනෙක් පිළිතුරු වලට වඩා වේගයෙන් ප්‍රගතියක් පෙන්නුම් කළ අතර එය පැය ගණනක් රැඳී ඇති බවක් පෙනේ. වගුව කළමනාකරණය කළ හැකි ප්‍රමාණයකට කප්පාදු කිරීමෙන් පසුව, ඔබට අනෙක් විමසුම් සමඟ අවසන් කළ හැකිය. ඉඟිය: col1 / col2 / col3 මගින් කාණ්ඩ අනුව දර්ශක ඇති බවට වග බලා ගන්න.
ක්ලෝයි

17
SELECT  DISTINCT *
      INTO tempdb.dbo.tmpTable
FROM myTable

TRUNCATE TABLE myTable
INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
DROP TABLE tempdb.dbo.tmpTable

5
ඔබට MyTable වෙත විදේශීය යතුරු යොමු කිරීම් තිබේ නම් කප්පාදු කිරීම ක්‍රියා නොකරනු ඇත.
සමීර් අලිබායි

15

මගේ විසඳුම විශේෂ තත්වයන් යටතේ ක්‍රියාත්මක වන බැවින් එය බෙදා ගැනීමට මම සිතුවෙමි. මගේ නඩුවේ අනුපිටපත් අගයන් සහිත වගුවට විදේශීය යතුරක් නොතිබුණි (අගයන් වෙනත් db එකකින් අනුපිටපත් කර ඇති නිසා).

begin transaction
-- create temp table with identical structure as source table
Select * Into #temp From tableName Where 1 = 2

-- insert distinct values into temp
insert into #temp 
select distinct * 
from  tableName

-- delete from source
delete from tableName 

-- insert into source from temp
insert into tableName 
select * 
from #temp

rollback transaction
-- if this works, change rollback to commit and execute again to keep you changes!!

PS: මේ වගේ දේවල් කරන විට මම නිතරම ගනුදෙනුවක් භාවිතා කරනවා, මෙය සියල්ල සමස්තයක් ලෙස ක්‍රියාත්මක වන බව සහතික කරනවා පමණක් නොව, කිසිවක් අවදානමට ලක් නොකර පරීක්ෂා කිරීමට මට ඉඩ සලසයි. නමුත් ඇත්ත වශයෙන්ම ඔබ කෙසේ හෝ උපස්ථයක් ගත යුතුය.


14

මෙම විමසුම මට ඉතා හොඳ කාර්ය සාධනයක් පෙන්නුම් කළේය:

DELETE tbl
FROM
    MyTable tbl
WHERE
    EXISTS (
        SELECT
            *
        FROM
            MyTable tbl2
        WHERE
            tbl2.SameValue = tbl.SameValue
        AND tbl.IdUniqueValue < tbl2.IdUniqueValue
    )

එය 2M (50% අනුපිටපත්) වගුවකින් තත්පර 30 ට වඩා අඩු 1M පේළි මකා දැමීය.


14

CTE භාවිතා කිරීම. අදහස වන්නේ අනුපිටපත් වාර්තාවක් සාදන තීරු එකක් හෝ වැඩි ගණනකට සම්බන්ධ වී ඔබ කැමති ඕනෑම දෙයක් ඉවත් කිරීමයි:

;with cte as (
    select 
        min(PrimaryKey) as PrimaryKey
        UniqueColumn1,
        UniqueColumn2
    from dbo.DuplicatesTable 
    group by
        UniqueColumn1, UniqueColumn1
    having count(*) > 1
)
delete d
from dbo.DuplicatesTable d 
inner join cte on 
    d.PrimaryKey > cte.PrimaryKey and
    d.UniqueColumn1 = cte.UniqueColumn1 and 
    d.UniqueColumn2 = cte.UniqueColumn2;

1
මම හිතන්නේ ඔබට ඔබගේ සම්බන්ධතාවයේ සහ නැතිවී ඇත.
ජස්ටින් ආර්.

13

මෙහි අලවා ඇති සබැඳියෙන් තවත් පහසු විසඳුමක් සොයාගත හැකිය . මෙය ග්‍රහණය කර ගැනීමට පහසු වන අතර සමාන ගැටළු බොහොමයකට effective ලදායී බව පෙනේ. එය SQL සේවාදායකය සඳහා වන නමුත් භාවිතා කරන සංකල්පය පිළිගත හැකි ප්‍රමාණයට වඩා වැඩිය.

සම්බන්ධිත පිටුවෙන් අදාළ කොටස් මෙන්න:

මෙම දත්ත සලකා බලන්න:

EMPLOYEE_ID ATTENDANCE_DATE
A001    2011-01-01
A001    2011-01-01
A002    2011-01-01
A002    2011-01-01
A002    2011-01-01
A003    2011-01-01

ඉතින් අපි එම අනුපිටපත් දත්ත මකා දැමිය හැක්කේ කෙසේද?

පළමුව, පහත කේතය භාවිතා කරමින් එම වගුවේ අනන්‍යතා තීරුවක් ඇතුළත් කරන්න:

ALTER TABLE dbo.ATTENDANCE ADD AUTOID INT IDENTITY(1,1)  

එය විසඳීමට පහත කේතය භාවිතා කරන්න:

DELETE FROM dbo.ATTENDANCE WHERE AUTOID NOT IN (SELECT MIN(AUTOID) _
    FROM dbo.ATTENDANCE GROUP BY EMPLOYEE_ID,ATTENDANCE_DATE) 

1
"ග්රහණය කර ගැනීමට පහසු", "ඵලදායී බව පෙනේ" නමුත්, ක්රමය සමන්විත දේ ගැන වචනයක් නොවේ. එකල භාවිතා කිරීමේ ක්රමයක් බව දැන ගැනීමට හැකි වනු ඇත දේ සබැඳිය වලංගු නොවන බවට පත් සිතාගත, විය ග්රහණය කර ගැනීමට පහසු සහ කාර්යක්ෂම? කරුණාකර ක්‍රමයේ විස්තරයේ අත්‍යවශ්‍ය කොටස් ඔබගේ ලිපියට එක් කිරීම ගැන සලකා බලන්න, එසේ නොමැතිනම් මෙය පිළිතුරක් නොවේ.
ඇන්ඩ්‍රි එම්

ඔබට තවමත් අනන්‍යතාවයක් අර්ථ දක්වා නොමැති වගු සඳහා මෙම ක්‍රමය ප්‍රයෝජනවත් වේ. ප්‍රාථමික යතුර නිර්වචනය කිරීම සඳහා බොහෝ විට ඔබ අනුපිටපත් ඉවත් කළ යුතුය!
ජෙෆ් ඩේවිස්

E ජෙෆ් ඩේවිස් - ROW_NUMBERඔබ ආරම්භ කිරීමට පෙර නව තීරුවක් එකතු කිරීමේ දිගට නොයා අනුවාදය එම අවස්ථාව සඳහා හොඳින් ක්‍රියා කරයි.
මාටින් ස්මිත්

12

අනුපිටපත් ඉවත් කිරීම පිළිබඳ තවත් හොඳ ලිපියක් මෙන්න .

එහි දෘ hard හේතුව කුමක්දැයි එය සාකච්ඡා කරයි: " SQL පදනම් වී ඇත්තේ සාපේක්ෂ වීජ ගණිතය මත වන අතර අනුපිටපත් වීජ ගණිතයේ සිදුවිය නොහැක, මන්ද කට්ටලයක අනුපිටපත් වලට ඉඩ නොදේ. "

තාවකාලික වගු විසඳුම සහ mysql උදාහරණ දෙකක්.

අනාගතයේදී ඔබ එය දත්ත සමුදා මට්ටමින් හෝ යෙදුම් දෘෂ්ටිකෝණයකින් වළක්වා ගැනීමට යන්නේ ය. යොමු දත්තවල අඛණ්ඩතාව පවත්වා ගැනීම සඳහා ඔබේ දත්ත ගබඩාව වගකිව යුතු බැවින් මම දත්ත සමුදා මට්ටම යෝජනා කරමි, සංවර්ධකයින් පමණක් ගැටළු ඇති කරයි;)


1
SQL පදනම් වී ඇත්තේ බහු-කට්ටල මත ය. නමුත් එය කට්ටල මත පදනම් වූවක් වුවද, මෙම ටුපල් දෙක (1, අ) සහ (2, අ) වෙනස් වේ.
ඇන්ඩෲ

12

විශ්වාසයි. තාවකාලික වගුවක් භාවිතා කරන්න. "ක්‍රියා කරන" තනි, එතරම් ක්‍රියාකාරී නොවන ප්‍රකාශයක් ඔබට අවශ්‍ය නම් ඔබට යා හැකිය:

DELETE FROM MyTable WHERE NOT RowID IN
    (SELECT 
        (SELECT TOP 1 RowID FROM MyTable mt2 
        WHERE mt2.Col1 = mt.Col1 
        AND mt2.Col2 = mt.Col2 
        AND mt2.Col3 = mt.Col3) 
    FROM MyTable mt)

මූලික වශයෙන්, වගුවේ එක් එක් පේළිය සඳහා, උප-තේරීම සලකා බලනු ලබන පේළියට හරියටම සමාන සියලු පේළි වල ඉහළ පේළිය සොයා ගනී. එබැවින් ඔබ "මුල්" අනුපිටපත් නොවන පේළි නියෝජනය කරන පේළි ලැයිස්තුවක් සමඟ අවසන් වේ.


11

අනුපිටපත් නොවන පේළි ආරක්ෂා කිරීමට අවශ්‍ය මේසයක් මා සතුව තිබුණි. වේගය හෝ කාර්යක්ෂමතාව ගැන මට විශ්වාස නැත.

DELETE FROM myTable WHERE RowID IN (
  SELECT MIN(RowID) AS IDNo FROM myTable
  GROUP BY Col1, Col2, Col3
  HAVING COUNT(*) = 2 )

7
මෙයින් උපකල්පනය කරන්නේ උපරිම වශයෙන් අනුපිටපත් 1 ක් ඇති බවයි.
මාටින් ස්මිත්

ඇයි නැත්තේ HAVING COUNT(*) > 1?
පිලිප් එම්

11

මෙය භාවිතා කරන්න

WITH tblTemp as
(
SELECT ROW_NUMBER() Over(PARTITION BY Name,Department ORDER BY Name)
   As RowNumber,* FROM <table_name>
)
DELETE FROM tblTemp where RowNumber >1

10

අනෙක් ක්‍රමය වන්නේ එකම ක්ෂේත්‍ර හා අද්විතීය දර්ශකය සහිත නව වගුවක් සාදන්න . ඉන්පසු සියලු දත්ත පැරණි වගුවේ සිට නව වගුව වෙත ගෙන යන්න . ස්වයංක්‍රීයව SQL SERVER නොසලකා හැරීම (අනුපිටපත් අගයක් තිබේ නම් කුමක් කළ යුතුද යන්න පිළිබඳ විකල්පයක් ද ඇත: නොසලකා හැරීම, බාධා කිරීම හෝ sth) අනුපිටපත් අගයන්. එබැවින් අපට අනුපිටපත් පේළි නොමැතිව එකම වගුව ඇත. ඔබට අද්විතීය දර්ශකය අවශ්‍ය නොවේ නම්, හුවමාරු දත්ත පසු ඔබට එය අතහැර දැමිය හැකිය .

විශේෂයෙන් විශාල වගු සඳහා ඔබේ නව අද්විතීය ලෙස සුචිගත කරන ලද වගුවට සියලු දත්ත වේගයෙන් මාරු කිරීම සඳහා ඔබට DTS (දත්ත ආනයනය / අපනයනය කිරීමට SSIS පැකේජය) භාවිතා කළ හැකිය. පේළි මිලියන 7 ක් සඳහා මිනිත්තු කිහිපයක් ගතවේ.


9

පහත විමසුම භාවිතා කිරීමෙන් අපට තනි තීරුව හෝ බහු තීරුව මත පදනම්ව අනුපිටපත් වාර්තා මකා දැමිය හැකිය. පහත විමසුම තීරු දෙකක් මත පදනම්ව මකා දමයි. වගුවේ නම: testingසහ තීරු නම්empno,empname

DELETE FROM testing WHERE empno not IN (SELECT empno FROM (SELECT empno, ROW_NUMBER() OVER (PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
or empname not in
(select empname from (select empname,row_number() over(PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)

9
  1. එකම ව්‍යුහයක් සහිත නව හිස් වගුවක් සාදන්න

  2. මේ වගේ විමසුමක් ක්‍රියාත්මක කරන්න

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) > 1
  3. ඉන්පසු මෙම විමසුම ක්‍රියාත්මක කරන්න

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) = 1

9

අනුපිටපත් මකා දැමීමට පහසුම ක්‍රමය මෙයයි

 DELETE FROM tblemp WHERE id IN 
 (
  SELECT MIN(id) FROM tblemp
   GROUP BY  title HAVING COUNT(id)>1
 )

http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105


කවුරුහරි මෙය ඉහළට ඔසවා තබන්නේ ඇයි? ඔබට එකම හැඳුනුම්පත දෙකකට වඩා තිබේ නම් මෙය ක්‍රියාත්මක නොවේ. ඒ වෙනුවට ලියන්න: හැඳුනුම්පත නොමැති තැන tblemp වෙතින් මකන්න (මාතෘකාව අනුව tblemp කාණ්ඩයෙන් min (id) තෝරන්න)
crellee

7

මෙම ප්‍රවේශය මෙන්ම එය ප්‍රයෝජනවත් විය හැකි බව මම සඳහන් කරමි, සහ සියලු SQL සේවාදායකයන් තුළ ක්‍රියා කරයි: බොහෝ විට ඇත්තේ එක් එකක් පමණි - අනුපිටපත් දෙකක්, සහ අයිඩී සහ අනුපිටපත් ගණන දනී. මේ අවස්ථාවේ දී:

SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0

7

යෙදුම් මට්ටමේ සිට (අවාසනාවකට). අද්විතීය දර්ශකයක් භාවිතා කිරීම තුළින් දත්ත සමුදාය මට්ටමින් අනුපිටපත් වැළැක්වීම සඳහා නිසි ක්‍රමය ඇති බව මම එකඟ වෙමි, නමුත් SQL Server 2005 හි දර්ශකයකට බයිට් 900 ක් පමණක් වීමට ඉඩ දී ඇති අතර මගේ වර්චාර් (2048) ක්ෂේත්‍රය එය ඉවතට විසි කරයි.

එය කොතරම් හොඳින් ක්‍රියාත්මක වේදැයි මම නොදනිමි, නමුත් ඔබට එය ක්‍රියාත්මක කිරීමට ප්‍රේරකයක් ලිවිය හැකි යැයි මම සිතමි, ඔබට එය දර්ශකයක් සමඟ කෙලින්ම කළ නොහැකි වුවද. වැනි දෙයක්:

-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism 
ON stories 
after INSERT, UPDATE 
AS 
    DECLARE @cnt AS INT 

    SELECT @cnt = Count(*) 
    FROM   stories 
           INNER JOIN inserted 
                   ON ( stories.story = inserted.story 
                        AND stories.story_id != inserted.story_id ) 

    IF @cnt > 0 
      BEGIN 
          RAISERROR('plagiarism detected',16,1) 

          ROLLBACK TRANSACTION 
      END 

එසේම, වර්චාර් (2048) මට මාළු ඇල්ලීමකි (ජීවිතයේ සමහර දේවල් බයිට් 2048 වේ, නමුත් එය සාමාන්‍ය දෙයක් නොවේ); එය සැබවින්ම වර්චර් (උපරිම) නොවිය යුතුද?



7
DELETE
FROM
    table_name T1
WHERE
    rowid > (
        SELECT
            min(rowid)
        FROM
            table_name T2
        WHERE
            T1.column_name = T2.column_name
    );

හායි ටීනා, මකාදැමීමේ අදහස් දැක්වීමෙන් පසුව ඔබට ඇලිස් නම ටී 1 වගුව මඟ හැරී ඇත.
නාගරාජ් එම්

6
CREATE TABLE car(Id int identity(1,1), PersonId int, CarId int)

INSERT INTO car(PersonId,CarId)
VALUES(1,2),(1,3),(1,2),(2,4)

--SELECT * FROM car

;WITH CTE as(
SELECT ROW_NUMBER() over (PARTITION BY personid,carid order by personid,carid) as rn,Id,PersonID,CarId from car)

DELETE FROM car where Id in(SELECT Id FROM CTE WHERE rn>1)

6

ඔබ ඉවත් කිරීමට බලාපොරොත්තු වන පේළි පෙරදසුන් කිරීමට මට අවශ්‍යය. Http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/ බලන්න

with MYCTE as (
  SELECT ROW_NUMBER() OVER (
    PARTITION BY DuplicateKey1
                ,DuplicateKey2 -- optional
    ORDER BY CreatedAt -- the first row among duplicates will be kept, other rows will be removed
  ) RN
  FROM MyTable
)
DELETE FROM MYCTE
WHERE RN > 1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.