Kiểm tra nếu các cột có giá trị giống nhau

sql
php

(Nghia Le) #1

Em có một bảng như thế này:

Group Status
1 2
1 2
1 2
1 2
2 1
2 2
2 3
3 2
3 4

Cho em hỏi làm sao để mình kiểm tra được nếu có group chứa tất cả phần tử đều đạt giá trị 2 ạ.
Ví dụ như hình trên thì nó sẽ in ra:

Group Status
1 2
1 2
1 2
1 2

Em xin cảm ơn ạ.


(rogp10) #2

Nếu ko quan tâm nó là gì thì dùng COUNT DISTINCT :slight_smile: và đọc query xplain.

Ngược lại ta dùng mệnh đề có lượng từ (EXISTS, ALL, SOME) và lấy đối của nó.


(Nghia Le) #3

dạ vâng em cũng đang suy nghĩ việc lấy kết quả đối của nó. Do khả năng về viết SQL còn hạn hẹp nên không biết được cách thực thi nó.
Anh có thể cho em biết hơn hoặc một số nguồn về cú pháp này được không ạ


(rogp10) #5

Các từ khóa kiểu lượng từ là <1 trong 6 toán tử so sánh> SOME (thay cho ANY)/ALL <query>, (NOT) EXISTS <query|table>, (NOT) IN <query>.
Yêu cầu là {x ∈ groups | ∀y: (x, y) ∈ table:(group, status), y = 2}
Ta có groups := $!(group).table
Viết lại !$(group).(r ∈ table | {∀s ∈ table | r.group = s.group, r.status = 2} để cho kết quả không trùng lắp.
Nhưng SQL chỉ có EXISTS ∃ nên dùng quy tắc phủ định để khẳng định, ta có kq là !$(group).{r ∈ table | (∄s ∈ table | r.group = s.group, r.status != (param:status := 2)}

Khi không cần quan tâm đến status nào:
$(group).{r ∈ table1:(group, count) | r.group ∈ groups && r.count = !#(status).{s ∈ table | s.group = r.group} = 1 }
hay là $(group).{r ∈ by(group).!#(status).table | r.count_status = 1}

p/s: trong bài này tất cả “tập hợp” đều là multi.

Bài này cũng giải thích vì sao trong SQL chuẩn không lấy được status trong các câu truy vấn sử dụng hàm tổng hợp.


(Hai Lúa) #6

Nguyên tắc để viết SQL là từ những đề bài, phân rã ra thành những cái đơn giản hơn, viết câu SQL trên những phần đơn giản, sau đó ráp lại.
Tiếp theo là tìm cách re-write lại câu SQL nếu có thể!

vd như câu trên:

  • Theo yêu cầu của bài, người ta ko thích những group có status # 2, nên chúng ta cần phải tìm những group này trước.
    SELECT c_group 
    FROM   tbl_test 
    WHERE  c_status != 2; 
    
  • Tiếp theo, lấy ra danh danh sách các group (va status) còn lại mà ko nằm trong những group trên.
    Cái này có thể dùng các toán tử như (NOT) IN, EXISTS hoặc MINUS, trong câu bên dưới chúng ta chọn dùng IN.
    SELECT * 
    FROM   tbl_test 
    WHERE  c_group **NOT IN** (SELECT c_group 
                             FROM   tbl_test 
                            WHERE  c_status != 2); 
    

Xong ! sau 2 bước chúng ta đã có kết quả như mong muốn.


83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?