Chỉ trích xuất cái đầu tiên từ đơn vị bản ghi nơi giá trị của cột được chỉ định được sao chép

Trang Cập Nhật :
Ngày tạo trang :

Thông thường, khi chỉ trích xuất một bản ghi trùng lặp, điều đầu tiên tôi nghĩ là distinct , distinct không cho phép bạn chỉ định một cột trùng lặp và một cột khác mà bạn muốn truy xuất cùng một lúc. Ngoài ra,distinct không phù hợp với yêu cầu này vì nó bao gồm các bản ghi không trùng lặp trong trích xuất.

Tôi không nghĩ bạn có thể hiểu những gì bạn muốn làm chỉ với tiêu đề, vì vậy hãy sử dụng một bản ghi mẫu làm ví dụ. Những gì tôi muốn làm là kết quả trích xuất sau.

Tên ID
1 Tên 1
2 Tên 2
3 Tên 3
3 Tên 3@example.com
4 Tên 4 Tên 4@example.com
4 Tên 4@example.com
4 Tên 4@example.com

Nhận nó như sau:

Tên ID
3 Tên 3@example.com
4 Tên 4@example.com

ID 1 và 2 không được bao gồm vì chúng không trùng lặp. ID 3 và 4 là trùng lặp, vì vậy một trong số chúng được truy xuất. Tuy nhiên, lần này, chúng tôi sẽ không nhận được bản ghi đầu tiên trong thứ tự lưu trữ CSDL. Ngoài ra, giả sử rằng bạn muốn dòng đầu tiên của tên theo thứ tự ưu tiên trong các điều kiện "Tên chứa dấu @" và "Tên có một số ký tự nhỏ".

Điều kiện trên có thể đạt được với SQL sau. Tuy nhiên, chúng tôi đang sử dụng các truy vấn phụ và chưa kiểm tra hiệu suất.

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)
)

Các hàng trùng lặp được having kiểm tra bằng và count . group by Cột chính cần kiểm tra từ bên ngoài, ở đây ID cột được where thu hẹp bằng .

Thứ tự ưu tiên để truy xuất hàng đầu tiên được order by chỉ định bởi . charindex Tại đây và len kiểm tra xem nó có chứa ký tự được chỉ định và độ dài của chuỗi hay không. top Tất cả những gì bạn cần làm là lấy hàng đầu tiên của mỗi bản ghi trùng lặp trong .

Ban đầu, điều này là tốt, nhưng nếu có hai hoặc nhiều bản ghi có cùng giá trị, chẳng hạn như "ID: 4, Tên: Tên 4@example.com", bạn chắc chắn sẽ nhận được hai bản ghi. row_number Do đó, nó được thêm vào để nó có thể được xác định cho mỗi hàng với , để chỉ có thể truy xuất một bản ghi có cùng giá trị. Nếu biết rằng không tồn tại cùng một bản ghi, tôi row_number nghĩ sẽ tốt hơn nếu kiểm tra các giá trị của các bản ghi hiện có mà không cần thêm .

Nếu có nhiều khóa cần kiểm tra để tìm trùng lặp, bạn có thể tăng số lượng cột khóa cho mỗi khóa. Ví dụ, hãy xem xét bản ghi sau đây: Các cột được kiểm tra để tìm trùng lặp là "ID1" và "ID2".

ID1Tên ID2
1 1 Tên 1
2 1 Tên 2
3 1 Tên 31
3 2 Tên 32
4 1 Tên41
4 2 Tên42
4 2 Tên 4@example.com
5 1 Tên 555@example.com
5 1 Tên 55@example.com
5 2 Tên 5@example.com
6 1 Tên 6
6 1 Tên 66@example.com
6 2 Tên 6
6 2 Tên 6

Kết quả mua lại như sau.

ID1Tên ID2
4 2 Tên 4@example.com
5 1 Tên 55@example.com
6 1 Tên 66@example.com
6 2 Tên 6

SQL trông như thế này: Bạn có thể chỉ cần tăng phần mà cột khóa đã được chỉ định.

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)
)