فقط اولین مورد را از واحد رکورد که مقدار ستون مشخص شده در آن کپی شده است استخراج کنید

صفحه به روز شده :
تاریخ ایجاد صفحه :

به طور معمول، هنگام استخراج فقط یک رکورد تکراری، اولین چیزی که به ذهنم می رسد این distinct است که فکر می کنم، distinct به شما اجازه نمی دهد یک ستون تکراری و ستون دیگری را که می خواهید به طور همزمان بازیابی کنید مشخص کنید. علاوه بر این،distinct با این نیاز مطابقت ندارد زیرا شامل سوابق غیر تکراری در استخراج است.

فکر نمی کنم بتوانید بفهمید که می خواهید با عنوان به تنهایی چه کاری انجام دهید، بنابراین بیایید از یک نمونه رکورد به عنوان مثال استفاده کنیم. کاری که می خواهم انجام دهم نتیجه استخراج زیر است.

نام شناسه
1 نام 1
2 نام 2
3 نام 3
3 نام 3@example.com
4 نام 4 نام 4@example.com
4 نام 4@example.com
4 نام 4@example.com

آن را به صورت زیر دریافت کنید:

نام شناسه
3 نام 3@example.com
4 نام 4@example.com

شناسه های 1 و 2 گنجانده نشده اند زیرا تکراری نیستند. شناسه های 3 و 4 تکراری هستند، بنابراین یکی از آنها بازیابی می شود. با این حال، این بار، ما اولین رکورد را در ترتیب ذخیره سازی DB دریافت نخواهیم کرد. علاوه بر این، فرض کنید که خط اول نام را به ترتیب اولویت تحت شرایطی می خواهید که "نام حاوی علامت @ است" و "نام تعداد کمی کاراکتر دارد".

شرط فوق را می توان با SQL زیر به دست آورد. با این حال، ما از پرس و جوهای فرعی استفاده می کنیم و عملکرد را بررسی نکرده ایم.

select
  *
from
  (select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
  select
    top(1) RowNum
  from
    (select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableSub
  where
        tableMain.ID = tableSub.ID
    and exists ( 
      select
        *
      from
        SampleTable
      where
        tableSub.ID = ID
      having
        count(*) >= 2
    )
  order by
    case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)

ردیف having های تکراری با و count بررسی می شوند. group by ستون کلیدی که باید از بیرون بررسی شود، در اینجا ID ستون where با باریک می شود.

ترتیب اولویت برای بازیابی ردیف order by اول با . charindex در اینجا، و len بررسی کنید که آیا حاوی کاراکتر مشخص شده و طول رشته است یا خیر. top تنها کاری که باید انجام دهید این است که ردیف اول هر رکورد تکراری را در .

در اصل، این خوب است، اما اگر دو یا چند رکورد با مقدار دقیقا یکسان وجود داشته باشد، مانند "ID: 4، Name: Name 4@example.com"، به ناچار دو رکورد دریافت خواهید کرد. row_number بنابراین ، به گونه ای اضافه می شود که بتوان آن را برای هر ردیف با ، شناسایی کرد ، به طوری که فقط یک رکورد با دقیقا همان مقدار قابل بازیابی است. اگر مشخص است که دقیقا همان رکورد وجود ندارد، فکر می کنم row_number بهتر است مقادیر سوابق موجود را بدون ضمیمه کردن بررسی کنیم.

اگر چندین کلید وجود دارد که باید برای موارد تکراری بررسی شوند، می توانید تعداد ستون های کلید را برای هر کدام افزایش دهید. به عنوان مثال، رکورد زیر را در نظر بگیرید: ستون هایی که باید برای موارد تکراری بررسی شوند "ID1" و "ID2" هستند.

نام
ID1ID2
1 1 نام 1
2 1 نام 2
3 1 نام 31
3 2 نام 32
4 1 نام و نام خانوادگی41
4 2 نام و نام خانوادگی42
4 2 نام 4@example.com
5 1 نام 555@example.com
5 1 نام 55@example.com
5 2 نام 5@example.com
6 1 نام 6
6 1 نام 66@example.com
6 2 نام 6
6 2 نام 6

نتیجه اکتساب به شرح زیر است.

نام
ID1ID2
4 2 نام 4@example.com
5 1 نام 55@example.com
6 1 نام 66@example.com
6 2 نام 6

SQL به این شکل است: شما به سادگی می توانید بخشی را که ستون کلید مشخص شده است افزایش دهید.

select
  *
from
  (select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
  select
    top(1) RowNum
  from
    (select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableSub
  where
        tableMain.ID1 = tableSub.ID1
    and tableMain.ID2 = tableSub.ID2
    and exists ( 
      select
        *
      from
        SampleTable
      where
            tableSub.ID1 = ID1
        and tableSub.ID2 = ID2
      having
        count(*) >= 2
    )
  order by
    case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)