استخرج الأول فقط من وحدة السجل حيث يتم تكرار قيمة العمود المحدد
عادة ، عند استخراج سجل مكرر واحد فقط ، فإن أول ما يتبادر إلى الذهن هو 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".
اسم | ID1 | ID2 |
---|---|---|
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 |
نتيجة الاستحواذ هي كما يلي.
اسم | ID1 | ID2 |
---|---|---|
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)
)