2010-02-08 28 views
5

Nếu tôi có một bảng như sau:Cách lấy tập hợp các hàng duy nhất từ ​​SQL trong đó tính duy nhất được xác định bởi 2 cột?

ID | Tên | Chuyên mục | Cha mẹ | URL | LastModified

Nếu hai hàng có cùng tên và cha, thì chúng không phải là duy nhất. Làm cách nào để tôi nhận được tập hợp các hàng duy nhất trong trường hợp này (nhưng trả lại nhiều hơn các cột khiến chúng trở thành duy nhất)?

Vì vậy, để biết thêm chi tiết: Đây là bảng từ khóa của công ty, nơi từ khóa được sắp xếp theo danh mục. Mỗi từ khóa chỉ có thể có một danh mục. Mỗi từ khóa có thể có từ khóa con, vì vậy nếu cha mẹ = 0 hoặc NULL, nó là một từ khóa gốc. Nếu từ khóa có cùng tên và cha mẹ trong một danh mục, thì chúng không phải là duy nhất (bất kể các cột khác). Nếu hai từ khóa có cùng tên và danh mục, và parent = 0 hoặc NULL thì chúng không phải là duy nhất. Nếu có bản sao, thì tôi chỉ muốn bản sao thứ nhất. Lý do là tôi đưa những thứ này vào một hệ thống mà sẽ không cho phép một từ khóa có hai đứa trẻ có cùng tên.

Tôi cũng muốn xem những hàng nào trùng lặp để xem điều gì gây ra rắc rối cho tôi!

Cảm ơn một triệu cho đến nay để có phản hồi tuyệt vời. Tôi rõ ràng không phải là một anh chàng SQL ... :(

+0

Bạn đang cố gắng làm gì? Các danh mục cho Tên/Phụ huynh? –

+0

Thiếu thông số kỹ thuật: Nếu hai hàng có cùng một tên gốc và tên, bạn có muốn trả lại chỉ một trong số chúng hay không. Nếu cái cũ, cái nào? –

+0

Thiếu thông số kỹ thuật: Điều gì sẽ xảy ra nếu hai hàng có cùng tên, nhưng cả hai hàng đều được đặt thành NULL? Điều này có nghĩa là chúng không phải là duy nhất? –

Trả lời

4

Truy vấn này tìm tất cả các hàng không có hàng khác có cùng tên và cha mẹ. Nếu hai hàng có cha được đặt thành NULL, các hàng này không được coi là có cùng một gốc.

SELECT T1.* 
FROM Table1 T1 
LEFT JOIN Table1 T2 
ON T1.ID != T2.ID AND T1.Name = T2.Name AND T1.Parent = T2.Parent 
WHERE T2.ID IS NULL 
+0

+1 Điều này cũng sẽ làm việc – Andomar

+0

Tôi ngạc nhiên khi bạn chấp nhận câu trả lời này vì nó không đáp ứng đặc điểm kỹ thuật bổ sung mà bạn đã thêm 'Nếu các hàng có cùng tên gốc và tên, hãy trả về một trong hai.' Tôi nghĩ rằng đề nghị đầu tiên của Andomar là mặc dù. –

7

Điều đó tùy thuộc vào những gì bạn muốn làm với các hàng không phải duy nhất.Nếu bạn không có chúng trong tập hợp kết quả, bạn có thể sử dụng nhóm theo và có:

select Name, Parent, Max(Category) 
from Table 
group by Name, Parent 
having count(*) = 1 

bạn cần Max (thể loại) bởi vì bạn đang không tập trung theo cột rằng, mặc dù có sẽ chỉ có một hàng cho mỗi Tên và phụ huynh.

Nếu mặc dù vậy, bạn muốn bao gồm phi các hàng duy nhất trong kết quả, tương tự như:

select distinct Name, Parent, Category from Table 

ngoại trừ hai hàng có cùng Tên và Phụ huynh nhưng Danh mục khác nhau chỉ trả lại một hàng. Trong trường hợp đó, bạn cần phải quyết định những gì để hiển thị cho Danh mục, vì nhiều hơn một hàng sẽ được cô đặc xuống một. Bạn vẫn có thể sử dụng Max (Category) hoặc Min (Category) và nhóm theo, nhưng bỏ qua việc có.

select Name, Parent, Max(Category) 
from Table 
group by Name, Parent 
+0

Điều đó sẽ chỉ trả lại một hàng, tuy nhiên, danh mục "tối đa" cho Tên/Phụ huynh đã cho. –

+0

Đó là những gì anh ta muốn, tất cả các hàng duy nhất (dựa trên tên và phụ huynh) và danh mục mỗi hàng thuộc về. –

+0

Có thể không có nhiều hơn một danh mục được bao gồm cho một Tên/Cha mẹ cụ thể không? Nếu có, thì nhiều hơn một danh mục sẽ được trả lại. (Đoán chúng ta sẽ cần phải tìm ra điều đó từ OP.) –

2

Bạn có thể sử dụng chức năng row_number để phân vùng theo Tên và phụ huynh, như:

select * 
from (
    select 
     row_number() over (partition by Name, Parent 
          order by Name, Parent) as rn 
    , * 
    from YourTable 
) sub 
where rn = 1 -- Only first row for a name/parent combination 

Nếu bạn đang tìm kiếm để chỉ chọn hàng mà là duy nhất, theo nghĩa là không có hàng khác với cùng tên và mẹ tồn tại, hãy thử:

select * 
from YourTable a 
where (
    select count(*) 
    from YourTable b 
    where a.Name = b.Name 
    and a.Parent = b.Parent 
) = 1 
+0

+1 cho đề xuất row_number. Lệnh 'by' của bạn khá là vô ích - nó sẽ có ý nghĩa hơn nếu đặt theo một trong các cột không có trong phân vùng, ví dụ id. Tôi đã hỏi một câu hỏi làm rõ về điều này như là một bình luận cho câu hỏi nhưng chưa nhận được câu trả lời nào được nêu ra, vì vậy không rõ hàng nào anh ta muốn trong tình huống này. –

1
select x,y,z 
from tablename t1 
where not exists (select 1 from tablename t2 where t2.name = t1.name and t1.parent = t2.parent and t2.id <> t1.id) 

có thể chạy chậm tùy thuộc vào kích thước bảng

+0

+1 Hoặc thử 'chọn *' :) – Andomar

Các vấn đề liên quan