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