Làm cách nào để (hoặc tôi có thể) CHỌN DISTINCT trên nhiều cột?

429
sheats 2008-09-11 05:33.

Tôi cần truy xuất tất cả các hàng từ một bảng trong đó 2 cột được kết hợp đều khác nhau. Vì vậy, tôi muốn tất cả các đợt bán hàng không có đợt bán hàng nào khác diễn ra trong cùng một ngày với cùng một mức giá. Doanh số duy nhất dựa trên ngày và giá sẽ được cập nhật sang trạng thái hoạt động.

Vì vậy, tôi đang nghĩ:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

Nhưng não tôi đau khi đi xa hơn thế.

5 answers

459
Joel Coehoorn 2008-09-11 05:36.
SELECT DISTINCT a,b,c FROM t

khoảng tương đương với:

SELECT a,b,c FROM t GROUP BY a,b,c

Bạn nên làm quen với cú pháp GROUP BY, vì nó mạnh hơn.

Đối với truy vấn của bạn, tôi sẽ làm như thế này:

UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
    SELECT id
    FROM sales S
    INNER JOIN
    (
        SELECT saleprice, saledate
        FROM sales
        GROUP BY saleprice, saledate
        HAVING COUNT(*) = 1 
    ) T
    ON S.saleprice=T.saleprice AND s.saledate=T.saledate
 )
352
Erwin Brandstetter 2012-09-28 14:50.

Nếu bạn tổng hợp các câu trả lời cho đến nay, làm sạch và cải thiện, bạn sẽ đến truy vấn vượt trội này:

UPDATE sales
SET    status = 'ACTIVE'
WHERE  (saleprice, saledate) IN (
    SELECT saleprice, saledate
    FROM   sales
    GROUP  BY saleprice, saledate
    HAVING count(*) = 1 
    );

Đó là nhiều nhanh hơn so với cả hai người. Đánh giá hiệu suất của câu trả lời hiện được chấp nhận bởi hệ số 10 - 15 (trong các thử nghiệm của tôi trên PostgreSQL 8.4 và 9.1).

Nhưng điều này vẫn còn xa là tối ưu. Sử dụng NOT EXISTSbán nối (chống) để có hiệu suất tốt hơn. EXISTSlà SQL tiêu chuẩn, đã tồn tại mãi mãi (ít nhất là kể từ PostgreSQL 7.2, rất lâu trước khi câu hỏi này được đặt ra) và hoàn toàn phù hợp với các yêu cầu được trình bày:

UPDATE sales s
SET    status = 'ACTIVE'
WHERE  NOT EXISTS (
   SELECT FROM sales s1                     -- SELECT list can be empty for EXISTS
   WHERE  s.saleprice = s1.saleprice
   AND    s.saledate  = s1.saledate
   AND    s.id <> s1.id                     -- except for row itself
   )
AND    s.status IS DISTINCT FROM 'ACTIVE';  -- avoid empty updates. see below

db <> fiddle here
Old SQL Fiddle

Phím duy nhất để xác định hàng

Nếu bạn không có khóa chính hoặc khóa duy nhất cho bảng ( idtrong ví dụ), bạn có thể thay thế bằng cột hệ thống ctidcho mục đích của truy vấn này (nhưng không phải cho một số mục đích khác):

   AND    s1.ctid <> s.ctid

Mỗi bảng phải có một khóa chính. Thêm một nếu bạn chưa có. Tôi đề xuất một serialhoặc một IDENTITYcột trong Postgres 10+.

Có liên quan:

  • Tạo trình tự theo thứ tự
  • Cột bảng tăng dần tự động

Làm thế nào là điều này nhanh hơn?

Truy vấn phụ trong phép EXISTSnối bán chống có thể ngừng đánh giá ngay khi tìm thấy bản dupe đầu tiên (không cần tìm hiểu thêm). Đối với một bảng cơ sở có ít bản sao, điều này chỉ hiệu quả hơn một chút. Với rất nhiều các bản sao này trở thành cách hiệu quả hơn.

Loại trừ các bản cập nhật trống

Đối với các hàng đã có status = 'ACTIVE'bản cập nhật này sẽ không thay đổi bất kỳ điều gì, nhưng vẫn chèn một phiên bản hàng mới với đầy đủ chi phí (áp dụng ngoại lệ nhỏ). Thông thường, bạn không muốn điều này. Thêm một WHEREđiều kiện khác như đã trình bày ở trên để tránh điều này và làm cho nó nhanh hơn:

Nếu statusđược xác định NOT NULL, bạn có thể đơn giản hóa thành:

AND status <> 'ACTIVE';

Kiểu dữ liệu của cột phải hỗ trợ <>toán tử. Một số loại như jsonkhông. Xem:

  • Làm thế nào để truy vấn một cột json cho các đối tượng trống?

Sự khác biệt tinh tế trong xử lý NULL

Truy vấn này (không giống như câu trả lời hiện được Joel chấp nhận ) không coi các giá trị NULL là bằng nhau. Hai hàng sau cho (saleprice, saledate)sẽ đủ điều kiện là "khác biệt" (mặc dù trông giống hệt mắt người):

(123, NULL)
(123, NULL)

Cũng chuyển trong một chỉ mục duy nhất và hầu như ở bất kỳ nơi nào khác, vì các giá trị NULL không so sánh bằng nhau theo tiêu chuẩn SQL. Xem:

  • Tạo ràng buộc duy nhất với các cột rỗng

OTOH, GROUP BY, DISTINCThoặc DISTINCT ON ()giá trị điều trị NULL như bằng nhau. Sử dụng kiểu truy vấn thích hợp tùy thuộc vào những gì bạn muốn đạt được. Bạn vẫn có thể sử dụng truy vấn nhanh hơn này IS NOT DISTINCT FROMthay vì =cho bất kỳ hoặc tất cả các so sánh để làm cho so sánh NULL bằng nhau. Hơn:

  • Cách xóa các hàng trùng lặp mà không có số nhận dạng duy nhất

Nếu tất cả các cột được so sánh đều được xác định NOT NULL, thì không có chỗ cho sự bất đồng.

25
Christian Berg 2008-09-11 06:17.

Vấn đề với truy vấn của bạn là khi sử dụng mệnh đề GROUP BY (mà về cơ bản bạn thực hiện bằng cách sử dụng riêng biệt), bạn chỉ có thể sử dụng các cột mà bạn nhóm theo hoặc tổng hợp các hàm. Bạn không thể sử dụng id cột vì có thể có các giá trị khác nhau. Trong trường hợp của bạn, luôn chỉ có một giá trị vì mệnh đề HAVING, nhưng hầu hết các RDBMS không đủ thông minh để nhận ra điều đó.

Tuy nhiên, điều này sẽ hoạt động (và không cần tham gia):

UPDATE sales
SET status='ACTIVE'
WHERE id IN (
  SELECT MIN(id) FROM sales
  GROUP BY saleprice, saledate
  HAVING COUNT(id) = 1
)

Bạn cũng có thể sử dụng MAX hoặc AVG thay vì MIN, điều quan trọng là sử dụng một hàm trả về giá trị của cột nếu chỉ có một hàng phù hợp.

1
frans eilering 2018-01-13 21:56.

Tôi muốn chọn các giá trị riêng biệt từ một cột 'GrondOfLucht' nhưng chúng phải được sắp xếp theo thứ tự như đã cho trong cột 'sắp xếp'. Tôi không thể nhận các giá trị riêng biệt của chỉ một cột bằng cách sử dụng

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

Nó cũng sẽ cung cấp cho cột 'sortering' và vì 'GrondOfLucht' VÀ 'sortering' không phải là duy nhất, kết quả sẽ là TẤT CẢ các hàng.

sử dụng GROUP để chọn các bản ghi của 'GrondOfLucht' theo thứ tự được đưa ra bởi 'sortering

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
1
Abdulhafeth Sartawi 2019-01-31 22:52.

Nếu DBMS của bạn không hỗ trợ phân biệt với nhiều cột như thế này:

select distinct(col1, col2) from table

Nói chung, nhiều lựa chọn có thể được thực hiện một cách an toàn như sau:

select distinct * from (select col1, col2 from table ) as x

Vì điều này có thể hoạt động trên hầu hết các DBMS và điều này dự kiến ​​sẽ nhanh hơn so với nhóm theo giải pháp vì bạn đang tránh chức năng nhóm.

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Các luật sư của Trump muốn vụ kiện Stormy Daniels được giải quyết trước mắt công chúng

Các luật sư của Trump muốn vụ kiện Stormy Daniels được giải quyết trước mắt công chúng

Ảnh: Getty Nếu có vẻ như câu chuyện Stormy Daniels-Donald Trump là một trò chơi bất tận giữa các luật sư (một số người trong số họ rất ngu ngốc), đó là bởi vì nó là. Vào thứ Hai, các luật sư đại diện cho luật sư của Trump, Michael Cohen và Trump đã thực hiện vở kịch mới nhất của họ: một đề nghị để vụ việc được quyết định bởi một trọng tài riêng.

Colin Trevorrow sẽ trở lại để chỉ đạo phần ba của phim thế giới kỷ Jura

Colin Trevorrow sẽ trở lại để chỉ đạo phần ba của phim thế giới kỷ Jura

Chris Pratt và Colin Trevorrow trên phim trường Jurassic World. Người đàn ông đầu tiên mạo hiểm vào Thế giới kỷ Jura sẽ trở lại đó cho phần cuối của bộ ba.

Bạn sẽ phân biệt chủng tộc như thế nào nếu người da đen thực sự có thể phân biệt chủng tộc?

Bạn sẽ phân biệt chủng tộc như thế nào nếu người da đen thực sự có thể phân biệt chủng tộc?

Một trong những điều thất vọng lớn nhất trong cuộc đời tôi - có lẽ thực sự là thất vọng lớn nhất - là người da đen ở Mỹ không có khả năng phân biệt chủng tộc. Chúng ta có thể cố gắng hết sức và ghét nhất có thể, nhưng do cách thức hoạt động của chủ nghĩa phân biệt chủng tộc, chúng ta sẽ không bao giờ có thể sử dụng tình trạng được săn đón là “phân biệt chủng tộc.

Bạn không cần phải xả những củ khoai tây nghiền này ngay lập tức

Bạn không cần phải xả những củ khoai tây nghiền này ngay lập tức

Một trong những thứ yêu thích của tôi để nấu trong Instant Pot (hoặc bất kỳ nồi áp suất nào) là các loại rau củ, nếu không sẽ mất nhiều thời gian hơn. Khoai tây chắc chắn thuộc loại này, đặc biệt là vì bạn có thể làm khoai tây nghiền hoàn toàn như kem hoàn toàn trong Nồi ăn liền mà không cần xả nước.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language