Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách dùng DISTINCT loại bỏ trùng lặp trong SQLite Android

DISTINCT trong SQLite - Loại bỏ bản ghi trùng lặp

Từ khóa DISTINCT trong SQL dùng để trả về các giá trị duy nhất (unique), loại bỏ các dòng trùng lặp hoàn toàn trong kết quả truy vấn.

Bước 1: Tạo dự án

Android Studio → File → New Project.

Bước 2: Giao diện (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Nhập tên" />

    <EditText
        android:id="@+id/salary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Nhập lương"
        android:inputType="numberDecimal" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp">

        <Button android:id="@+id/save" android:text="Lưu" android:layout_width="wrap_content" android:layout_height="wrap_content" />
        <Button android:id="@+id/refresh" android:text="Làm mới" android:layout_width="wrap_content" android:layout_height="wrap_content" />
        <Button android:id="@+id/update" android:text="Cập nhật" android:layout_width="wrap_content" android:layout_height="wrap_content" />

    </LinearLayout>

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp" />

</LinearLayout>

Bước 3: MainActivity.java

package com.example.sqlitedistinct;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    Button btnSave, btnRefresh;
    EditText edtName, edtSalary;
    ListView listView;
    DatabaseHelper dbHelper;
    ArrayList dataList;
    ArrayAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dbHelper = new DatabaseHelper(this);
        dataList = new ArrayList<>(dbHelper.getAllContacts());
        
        edtName = findViewById(R.id.name);
        edtSalary = findViewById(R.id.salary);
        listView = findViewById(R.id.listView);
        btnSave = findViewById(R.id.save);
        btnRefresh = findViewById(R.id.refresh);

        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataList);
        listView.setAdapter(adapter);

        btnRefresh.setOnClickListener(v -> {
            dataList.clear();
            dataList.addAll(dbHelper.getAllContacts());
            adapter.notifyDataSetChanged();
        });

        btnSave.setOnClickListener(v -> {
            String name = edtName.getText().toString().trim();
            String salary = edtSalary.getText().toString().trim();
            if (name.isEmpty() || salary.isEmpty()) {
                if (name.isEmpty()) edtName.setError("Nhập tên");
                if (salary.isEmpty()) edtSalary.setError("Nhập lương");
                return;
            }
            if (dbHelper.insert(name, salary)) {
                Toast.makeText(this, "Đã thêm", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Thêm thất bại", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Bước 4: DatabaseHelper.java - Quan trọng: DISTINCT

package com.example.sqlitedistinct;

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;

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "salaryDatabase";
    private static final String TABLE_NAME = "SalaryDetails";
    private static final int DB_VERSION = 1;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_NAME + 
            "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, salary TEXT, datetime DEFAULT CURRENT_TIMESTAMP)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }

    public boolean insert(String name, String salary) {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("name", name);
        cv.put("salary", salary);
        return db.insert(TABLE_NAME, null, cv) != -1;
    }

    // SỬ DỤNG DISTINCT ĐỂ LOẠI BỎ TRÙNG LẶP
    public ArrayList getAllContacts() {
        ArrayList list = new ArrayList<>();
        SQLiteDatabase db = getReadableDatabase();
        
        // Chỉ lấy tên duy nhất, sắp xếp theo name, salary
        Cursor cursor = db.rawQuery(
            "SELECT DISTINCT name FROM " + TABLE_NAME + " ORDER BY name, salary", null);

        if (cursor.moveToFirst()) {
            do {
                list.add(cursor.getString(cursor.getColumnIndex("name")));
            } while (cursor.moveToNext());
        }
        cursor.close();
        return list;
    }

    public boolean update(String name, String salary) {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("name", name);
        cv.put("salary", salary);
        return db.update(TABLE_NAME, cv, "name = ?", new String[]{name}) > 0;
    }

    public boolean deleteAll() {
        return getWritableDatabase().delete(TABLE_NAME, null, null) > 0;
    }
}

Giải thích DISTINCT

-- Chỉ lấy cột name duy nhất
SELECT DISTINCT name FROM SalaryDetails;

-- DISTINCT trên nhiều cột (kết hợp name + salary phải duy nhất)
SELECT DISTINCT name, salary FROM SalaryDetails;

-- Kết hợp với ORDER BY
SELECT DISTINCT name FROM SalaryDetails ORDER BY name ASC;

-- Kết hợp với COUNT
SELECT COUNT(DISTINCT name) FROM SalaryDetails;

So sánh: Không DISTINCT vs Có DISTINCT

Dữ liệu mẫu:

idnamesalary
1An1000
2Bình2000
3An1500
4Cường3000
5An1000

SELECT name FROM table: An, Bình, An, Cường, An (5 dòng)

SELECT DISTINCT name FROM table: An, Bình, Cường (3 dòng)

SELECT DISTINCT name, salary FROM table: (An,1000), (Bình,2000), (An,1500), (Cường,3000) (4 dòng)

Lưu ý hiệu năng

  • DISTINCT tốn tài nguyên hơn (phải sort/hash để loại trùng).
  • Nên tạo index trên cột dùng DISTINCT: CREATE INDEX idx_name ON SalaryDetails(name);
  • Tránh SELECT DISTINCT * - chỉ chọn cột cần thiết.