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

Sắp xếp 2 cột cùng lúc trong SQLite Android (ORDER BY nhiều cột)

Mục tiêu

Sử dụng mệnh đề ORDER BY column1, column2 trong SQLite để sắp xếp dữ liệu theo 2 cột cùng lúc (sắp xếp chính - phụ).

Ví dụ thực tế

Bảng lương nhân viên: sắp xếp theo Tên (A-Z) trước, nếu trùng tên thì sắp xếp theo Lương (tăng dần).

Các bước thực hiện

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

Android Studio → File → New Project → Empty Activity.

Bước 2: Layout (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"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edtName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Tên nhân viên" />

    <EditText
        android:id="@+id/edtSalary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Lương"
        android:inputType="numberDecimal" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnSave"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Lưu" />

        <Button
            android:id="@+id/btnRefresh"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Làm mới (ORDER BY)" />

        <Button
            android:id="@+id/btnUpdate"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Cập nhật" />

    </LinearLayout>

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

Bước 3: DatabaseHelper.java - QUAN TRỌNG

package com.example.sqliteorderby;

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 {

    private static final String DB_NAME = "salaryDatabase5";
    private static final String TABLE_NAME = "SalaryDetails";
    private static final int VERSION = 1;

    DatabaseHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // Thêm cột datetime mặc định current_timestamp
        db.execSQL("CREATE TABLE " + TABLE_NAME + 
            " (id INTEGER PRIMARY KEY, 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);
    }

    boolean insert(String name, String salary) {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("name", name);
        cv.put("salary", salary);
        // replace: insert hoặc update nếu id trùng (cần unique constraint trên name)
        return db.replace(TABLE_NAME, null, cv) != -1;
    }

    // TRUY VẤN CHÍNH: ORDER BY name ASC, salary ASC
    ArrayList<String> getAllContacts() {
        SQLiteDatabase db = getReadableDatabase();
        ArrayList<String> list = new ArrayList<>();
        
        Cursor cursor = db.rawQuery(
            "SELECT * FROM " + TABLE_NAME + " ORDER BY name ASC, salary ASC", 
            null
        );

        if (cursor.moveToFirst()) {
            do {
                String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
                String salary = cursor.getString(cursor.getColumnIndexOrThrow("salary"));
                list.add(name + " - " + salary + "đ");
            } while (cursor.moveToNext());
        }
        cursor.close();
        return list;
    }

    boolean update(String name, String salary) {
        SQLiteDatabase db = getWritableDatabase();
        // Cẩn thận: UPDATE không có WHERE sẽ cập nhật TẤT CẢ rows!
        // Nên dùng: UPDATE table SET salary=? WHERE name=?
        ContentValues cv = new ContentValues();
        cv.put("salary", salary);
        return db.update(TABLE_NAME, cv, "name=?", new String[]{name}) > 0;
    }

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

Bước 4: MainActivity.java

package com.example.sqliteorderby;

import android.os.Bundle;
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 androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private EditText edtName, edtSalary;
    private Button btnSave, btnRefresh, btnUpdate;
    private ListView listView;
    private DatabaseHelper helper;
    private ArrayList<String> dataList;
    private ArrayAdapter<String> adapter;

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

        helper = new DatabaseHelper(this);
        dataList = helper.getAllContacts();
        edtName = findViewById(R.id.edtName);
        edtSalary = findViewById(R.id.edtSalary);
        listView = findViewById(R.id.listView);
        btnSave = findViewById(R.id.btnSave);
        btnRefresh = findViewById(R.id.btnRefresh);
        btnUpdate = findViewById(R.id.btnUpdate);

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

        btnRefresh.setOnClickListener(v -> {
            dataList.clear();
            dataList.addAll(helper.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 (helper.insert(name, salary)) {
                Toast.makeText(this, "Đã lưu", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Lưu thất bại", Toast.LENGTH_SHORT).show();
            }
        });

        btnUpdate.setOnClickListener(v -> {
            String name = edtName.getText().toString().trim();
            String salary = edtSalary.getText().toString().trim();
            if (!name.isEmpty() && !salary.isEmpty()) {
                if (helper.update(name, salary)) {
                    Toast.makeText(this, "Đã cập nhật", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "Không tìm thấy", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

Giải thích ORDER BY nhiều cột

Cú pháp: ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...

  • Sắp xếp theo column1 trước
  • Nếu các giá trị column1 bằng nhau → sắp xếp tiếp theo column2
  • Mặc định là ASC (tăng dần). Dùng DESC cho giảm dần

Ví dụ dữ liệu:

namesalary
An5000
An3000
Bình4000
An7000

Kết quả ORDER BY name ASC, salary ASC:

  1. An - 3000
  2. An - 5000
  3. An - 7000
  4. Bình - 4000

Kết quả

Nhấn "Làm mới" → ListView hiển thị danh sách sắp xếp tên A-Z, cùng tên thì lương tăng dần.

Sắp xếp 2 cột cùng lúc trong SQLite Android (ORDER BY nhiều cột)

Sắp xếp 2 cột cùng lúc trong SQLite Android (ORDER BY nhiều cột)

Mở rộng

  • ORDER BY name COLLATE NOCASE ASC: Sắp xếp không phân biệt hoa/thường
  • ORDER BY salary DESC, name ASC: Lương giảm dần, tên tăng dần
  • Tạo index: CREATE INDEX idx_name_salary ON SalaryDetails(name, salary) để tối ưu ORDER BY