Toán tử INTERSECT
Trả về các hàng xuất hiện ở cả hai tập kết quả (giao của 2 tập hợp). Cả hai SELECT phải có cùng số cột và kiểu dữ liệu tương thích.
Ví dụ: INTERSECT trên cùng một bảng (demo)
DatabaseHelper.java
package com.example.intersectdemo;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
class DatabaseHelper extends SQLiteOpenHelper {
static final String DB_NAME = "salaryDatabase";
static final String TABLE = "SalaryDetails";
DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE +
"(id INTEGER PRIMARY KEY, name TEXT, salary REAL, datetime DEFAULT CURRENT_TIMESTAMP)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int old, int n) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
onCreate(db);
}
boolean insert(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("salary", salary);
db.insert(TABLE, null, cv);
return true;
}
// INTERSECT: name từ bảng A giao với name từ bảng B (cùng bảng demo)
ArrayList<String> getAllContacts() {
ArrayList<String> list = new ArrayList<>();
SQLiteDatabase db = getReadableDatabase();
Cursor c = db.rawQuery(
"SELECT name AS fullname FROM " + TABLE +
" INTERSECT SELECT name FROM " + TABLE, null);
if (c.moveToFirst()) {
do {
list.add(c.getString(c.getColumnIndexOrThrow("fullname")));
} while (c.moveToNext());
}
c.close();
return list;
}
boolean update(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("salary", salary);
db.update(TABLE, cv, "name=?", new String[]{name});
return true;
}
boolean delete() {
getWritableDatabase().delete(TABLE, null, null);
return true;
}
}
Kết quả
Vì INTERSECT cùng bảng với chính nó → kết quả là tất cả name distinct (giống SELECT DISTINCT name).
Ví dụ thực tế: 2 bảng khác nhau
-- Bảng employees (id, name, dept_id) -- Bảng managers (id, name, dept_id) -- Tìm nhân viên VÀ LÀ manager (cùng tên) SELECT name FROM employees INTERSECT SELECT name FROM managers;
Các toán tử tập hợp (Set Operations)
| Toán tử | Ý nghĩa | Ví dụ |
|---|---|---|
UNION | Hợp (distinct) | A ∪ B |
UNION ALL | Hợp (giữ trùng) | A + B |
INTERSECT | Giao | A ∩ B |
EXCEPT | Hiệu (A - B) | A \ B |
Quy tắc
- Số cột SELECT phải bằng nhau.
- Kiểu dữ liệu cột tương ứng phải tương thích.
- Kết quả tự động DISTINCT (trừ UNION ALL).
- Có thể dùng ORDER BY ở cuối câu truy vấn 전체.
Ứng dụng Android
- Tìm user có cả trong danh sách "VIP" và "Active".
- Lọc sản phẩm vừa trong kho vừa đang khuyến mãi.
- So sánh dữ liệu local vs server (sync).
Hiệu năng
INTERSECT thường chậm hơn JOIN/EXISTS trên bảng lớn. Nên index cột so sánh.
-- Thường nhanh hơn INTERSECT SELECT DISTINCT e.name FROM employees e JOIN managers m ON e.name = m.name;