แยกเฉพาะรายการแรกจากหน่วยระเบียนที่ค่าของคอลัมน์ที่ระบุซ้ํากัน
โดยปกติเมื่อแยกบันทึกที่ซ้ํากันเพียงแผ่นเดียวสิ่งแรกที่นึกถึงคือ 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 |
ไม่รวม ID 1 และ 2 เนื่องจากไม่ซ้ํากัน ID 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)
)