2012-07-17 1 views
5

Tôi đang cố tìm giá trị thấp nhất đầu tiên trong bảng và ngày xảy ra giá trị đó cho mỗi người dùng DISTINCT trong bảng.Tìm nạp giá trị thấp nhất ĐẦU TIÊN trong bảng và ngày xảy ra giá trị cho mỗi người dùng riêng biệt

Đây là schema bảng và một số dữ liệu mẫu:

CREATE TABLE diet_watch (
    entry_date date NOT NULL, 
    user_id int default 1, 
    weight  double precision NOT NULL 
); 

INSERT INTO diet_watch VALUES ('2001-01-01', 1, 128.2); 
INSERT INTO diet_watch VALUES ('2001-01-02', 1, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-03', 1, 122.3); 
INSERT INTO diet_watch VALUES ('2001-01-04', 1, 303.7); 
INSERT INTO diet_watch VALUES ('2001-01-05', 1, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-01', 2, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-06', 2, 128.0); 

SQL tôi đã đưa ra ở đây trong this snippet

Tôi đã kể từ khi được thông báo rằng nó là không chính xác, có lẽ ai đó có thể giải thích những gì vấn đề với SQL của tôi là gì?

Lưu ý: Tôi thích SQL ANSI nếu có thể, nhưng tôi đang sử dụng PostgreSQL, vì vậy nếu tôi phải sử dụng một hương vị cụ thể của SQL, nó phải hoạt động trên PG.

+0

Tôi không thể truy cập SQL hiện tại. Bạn có thể đăng truy vấn của mình không? – RedFilter

+0

@RedFilter - là SQL Fiddle không hoạt động cho bạn? Chuyện gì vậy? –

+0

@JakeFeasel Thật tuyệt ngay bây giờ - Tôi nghĩ máy chủ đã bị tấn công, trang mất vài phút để hiển thị. Nhưng không sao sau đó. – RedFilter

Trả lời

6

Lưu ý: Bạn không chắc chắn nếu chức năng Window là ANSI SQL

Chức năng WINDOW được một phần của SQL: 2003 đặc điểm kỹ thuật: http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function (Thx @a_horse_with_no_name)

Hãy thử điều này:

http://sqlfiddle.com/#!1/7aa4e/22

SELECT * 
    FROM 
    (
    SELECT a.*, 
      ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY weight) AS Position 
     FROM diet_watch a 

    ) a 
    WHERE a.Position = 1 
+0

Có, các chức năng cửa sổ ** là ** ANSI SQL (từ năm 2003). –

+0

@a_horse_with_no_name Đã cố gắng truy cập trực tuyến để đăng tại đây.Nếu bạn một tiện dụng bạn có thể pls gửi nó? – Chandu

+0

http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function –

1

Trước tiên, truy vấn của bạn là không cần thiết phức tạp. Bạn chỉ cần đặt nhóm vào trong truy vấn phụ và loại bỏ truy vấn bên ngoài.

Chức năng cửa sổ, được đề cập bởi @Chandu, là một giải pháp rất tốt. Nó là ANSI SQL và postgres hỗ trợ nó. Tuy nhiên, không phải tất cả cơ sở dữ liệu đều làm. Một giải pháp thay thế là:

select dw.* 
from diet_watch dw join 
    (select user_id, min(entry_date) as mindate 
     from diet_watch dw 
     group by user_id 
    ) dwmin 
    on dw.user_id = dwmin.user_id and dw.entry_date = dwmin.mindate 

Lý do truy vấn ban đầu của bạn không hoạt động là do entry_date tối thiểu có thể không có trọng lượng tối thiểu. Truy vấn của bạn truy xuất tối thiểu từng trường một cách độc lập. Phiên bản này tìm thấy ngày tối thiểu, sau đó tham gia trở lại bảng gốc để có được trọng lượng (và các thông tin khác) vào ngày đó.

+0

Thực ra gần như tất cả các chức năng cửa sổ hỗ trợ DBMS. Chỉ có rất ít điều không (đặc biệt là MySQL và SQLite) –

+0

+1, Chủ yếu cho giải thích tại sao truy vấn OP không thành công – dbenham

1

Nếu bạn đang tìm kiếm lần đầu tiên mỗi người dùng đạt được trọng lượng tối thiểu, tôi nghĩ rằng điều này có hiệu quả. Tôi thấy trong dữ liệu thử nghiệm, người dùng 1 đạt được mức tối thiểu 121 lần và bạn muốn ngày đầu tiên? Theo hiểu biết của tôi, điều này sẽ hoạt động trên mọi công cụ SQL.

SELECT min(dw.entry_date), dw.user_id, dw.weight FROM diet_watch dw, 
    (SELECT min(weight) AS "weight", user_id FROM diet_watch GROUP BY user_id) mins 
WHERE dw.user_id = mins.user_id AND dw.weight = mins.weight 
GROUP BY dw.user_id, dw.weight 

Chọn bên trong tìm trọng lượng tối thiểu của mỗi người dùng. Một phút khác là cần thiết vào ngày này, bởi vì nếu không bạn sẽ không chọn cụ thể lần đầu tiên trọng lượng tối thiểu đã đạt được cho người dùng đó.

http://sqlfiddle.com/#!1/7aa4e/51/0