chọn tất cả các hàng có giá trị tối thiểu


9

Trong Sqlite 3 Tôi đang cố gắng tìm ra cách chọn hàng dựa trên giá trị tối thiểu. Tôi nghĩ rằng tôi bị giới hạn bởi không biết đủ các thuật ngữ liên quan để tìm kiếm google một cách hiệu quả.

Bảng trông giống như:

num         text        num2      
----------  ----------  ----------
0           a           1         
0           a           2         
1           a           3         
1           b           4         

Tôi muốn nhận được hàng nơi num21, 2, và 4. Tôi muốn thực hiện lựa chọn dựa trên giá trị num tối thiểu cho mỗi giá trị duy nhất của cột văn bản.

Vì vậy, với text = 'a'giá trị tối thiểu num0, vì vậy tôi muốn hàng 1 và 2. Vì text = 'b', giá trị tối thiểu num1, vì vậy tôi muốn hàng 4.

Sử dụng kết hợp nhiều nhóm khác nhau theo, tôi có thể nhận được hàng 12hoặc hàng 14. Tôi cảm thấy như tôi đang thiếu một thành phần SQL sẽ làm những gì tôi muốn, nhưng tôi không thể tìm ra nó có thể là gì.

Cách thích hợp để làm loại truy vấn này là gì?

Giải pháp có thể

Tôi đã tìm thấy một cách để làm điều này. Tôi không đủ uy tín để trả lời câu hỏi của riêng mình, vì vậy tôi đang thực hiện cập nhật tại đây. Tôi không chắc liệu nó luôn luôn đúng hay hiệu quả là như thế nào. Mọi ý kiến ​​đều được chào đón.

Tôi đã sử dụng một câu lệnh chọn hỗn hợp, trong đó một truy vấn tìm giá trị tối thiểu của num cho mỗi giá trị duy nhất của văn bản:

sqlite> select num, text from t group by text having num = min( num );
num         text      
----------  ----------
0           a         
1           b         

Sau đó, tôi đã kết hợp điều này với bảng đầy đủ để có được tất cả các hàng khớp với hai cột này.

sqlite> with u as
      ( select num, text from t group by text having num = min( num ) )
        select t.* from t join u on t.num = u.num and t.text = u.text;
num         text        num2      
----------  ----------  ----------
0           a           1         
0           a           2         
1           b           4         

Câu trả lời:


10

Như bạn đã thấy, một NHÓM B BYNG đơn giản sẽ không hoạt động vì nó sẽ chỉ trả về một bản ghi cho mỗi nhóm.

Tham gia của bạn hoạt động tốt. Đối với một bảng lớn, nó sẽ chỉ hiệu quả nếu có một chỉ mục trên các cột nối ( numtext).

Ngoài ra, bạn có thể sử dụng truy vấn con tương quan:

SELECT *
FROM t
WHERE num = (SELECT MIN(num)
             FROM t AS t2
             WHERE t2.text = t.text);

SQLFiddle

Khi được thực thi, truy vấn này không yêu cầu bảng tạm thời (truy vấn của bạn cho kết quả của u), nhưng sẽ thực hiện truy vấn con cho mỗi bản ghi trong t, do đó textnên được lập chỉ mục. (Hoặc sử dụng một chỉ mục trên cả hai textnumđể có được một chỉ số bao trùm .)


anh ta không có bất kỳ bảng tạm thời nào trong truy vấn của mình, chỉ có một CTE, khá khác biệt.
ypercubeᵀᴹ

Khi được thực thi, kết quả của utruy vấn được lưu trữ trong một bảng tạm thời, bất kể nó được viết dưới dạng CTE, chế độ xem hay nội tuyến dưới dạng truy vấn con.
CL.

Cảm ơn, phiên bản này dễ viết hơn nhiều so với phiên bản tôi tình cờ đọc được. Biết thuật ngữ đúng cũng hữu ích cho tôi để xem xét vấn đề này nhiều hơn.
dùng35292

@CL Đó có phải là cách SQLite thực hiện các truy vấn với CTE? Bạn có một tài liệu tham khảo cho điều đó? Bởi vì các DBMS khác không nhất thiết phải sử dụng bảng tạm thời cho byte.
ypercubeᵀᴹ

@ypercube CTEs, lượt xem và truy vấn con được làm phẳng hoặc thực hiện dưới dạng coroutines, nếu có thể. Nhưng một NHÓM THEO trên một cột không được lập chỉ mục phải có khả năng thu thập dữ liệu cho tất cả các nhóm song song, do đó, nó yêu cầu một số dạng bảng tạm thời (trong tất cả các cơ sở dữ liệu).
CL.

1

Tôi có xu hướng làm điều này với một sự tham gia bên ngoài:

SELECT
    M1.Num,
    M1.Text,
    M1.Num2
FROM
    MyDb M1
LEFT OUTER JOIN
    MyDB M2
ON
    M1.text = M2.text
AND
    M1.num > m2.num
WHERE
    M2.num is null

Điều này về cơ bản là nói; cung cấp cho tôi tất cả các hồ sơ không có giá trị cao hơn tức là null.


1

Vì vậy, làm thế nào bạn có thể tìm thấy câu trả lời cho câu hỏi của bạn vào lần tới? Theo tôi, đó là bằng cách phân tách và tuân theo logic. Và bạn đã đúng:

Tôi muốn thực hiện lựa chọn dựa trên giá trị num tối thiểu cho mỗi giá trị duy nhất của cột văn bản

Điều này dịch là:

select text, min(num) from t group by text;

(Điều này sẽ tương đương với của bạn havingtruy vấn Nó có thể là thú vị để có một cái nhìn tại các hàng ở đâu. numBằng NULL được chính xác hơn. Có một cái nhìn gì có hiệu lực hàng với null có, mà bạn có thể muốn lọc ra đầu tiên với một where num is not null)

Từ đây bạn có thể đạt được kết quả mong muốn của mình bằng cách:

select * from t where (num, text) in ( *insert query above* )

Hoặc sử dụng tham gia:

select t1.* from t t1,
    (select text, min(num) as n from t group by text) t2
where t1.num = t2.n and t1.text = t2.text.

Và khi hiệu suất không đủ cho các bảng của bạn, hãy bắt đầu xem xét các câu lệnh phức tạp hơn.


-2

Không nên là truy vấn này chính xác những gì bạn cần?

select min(num), text, num2 group by text, num2

Điều này sẽ trả về tất cả bốn bản ghi, bởi vì các num2giá trị là duy nhất.
CL.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.