Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีแสดงข้อมูลเรียงลำดับ Descending ใน SQLite Android

ภาพรวม

SQLite เป็นฐานข้อมูล SQL แบบ Open Source ที่เก็บข้อมูลในไฟล์ข้อความบนอุปกรณ์ Android มี SQLite ในตัว รองรับฟีเจอร์ฐานข้อมูลเชิงสัมพันธ์ครบถ้วน

ตัวอย่างนี้สาธิตการใช้ ORDER BY ... DESC ใน SQLite เพื่อแสดงข้อมูลเรียงลำดับจากมากไปน้อย (Descending Order)

ขั้นตอนการสร้าง

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → File → New Project → กรอกรายละเอียด

ขั้นตอนที่ 2: จัดรูปแบบหน้าจอ (res/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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="ป้อนชื่อ" />

    <EditText
        android:id="@+id/salary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal"
        android:hint="ป้อนเงินเดือน" />

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

        <Button
            android:id="@+id/save"
            android:text="บันทึก"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:id="@+id/refresh"
            android:text="รีเฟรช"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:id="@+id/update"
            android:text="อัปเดต"
            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" />

</LinearLayout>

ขั้นตอนที่ 3: เขียนโค้ด MainActivity (src/MainActivity.java)

package com.example.andy.myapplication;

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 save, refresh;
    EditText name, salary;
    private ListView listView;

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

        final DatabaseHelper helper = new DatabaseHelper(this);
        final ArrayList<String> arrayList = helper.getAllContacts();

        name = findViewById(R.id.name);
        salary = findViewById(R.id.salary);
        listView = findViewById(R.id.listView);

        final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
            this, android.R.layout.simple_list_item_1, arrayList);
        listView.setAdapter(arrayAdapter);

        findViewById(R.id.refresh).setOnClickListener(v -> {
            arrayList.clear();
            arrayList.addAll(helper.getAllContacts());
            arrayAdapter.notifyDataSetChanged();
            listView.invalidateViews();
            listView.refreshDrawableState();
        });

        findViewById(R.id.save).setOnClickListener(v -> {
            String nameStr = name.getText().toString().trim();
            String salaryStr = salary.getText().toString().trim();

            if (!nameStr.isEmpty() && !salaryStr.isEmpty()) {
                if (helper.insert(nameStr, salaryStr)) {
                    Toast.makeText(this, "บันทึกสำเร็จ", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, "บันทึกไม่สำเร็จ", Toast.LENGTH_LONG).show();
                }
            } else {
                name.setError("กรุณาป้อนชื่อ");
                salary.setError("กรุณาป้อนเงินเดือน");
            }
        });
    }
}

ขั้นตอนที่ 4: สร้าง DatabaseHelper (src/DatabaseHelper.java)

package com.example.andy.myapplication;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.IOException;
import java.util.ArrayList;

class DatabaseHelper extends SQLiteOpenHelper {
    public static final String DATABASE_NAME = "salaryDatabase5";
    public static final String CONTACTS_TABLE_NAME = "SalaryDetails";

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.execSQL("CREATE TABLE " + CONTACTS_TABLE_NAME + 
                "(id INTEGER PRIMARY KEY, name TEXT, salary TEXT, datetime DEFAULT CURRENT_TIMESTAMP)");
        } catch (SQLiteException e) {
            try { throw new IOException(e); } 
            catch (IOException e1) { e1.printStackTrace(); }
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + CONTACTS_TABLE_NAME);
        onCreate(db);
    }

    public boolean insert(String name, String salary) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("name", name);
        values.put("salary", salary);
        db.replace(CONTACTS_TABLE_NAME, null, values);
        return true;
    }

    public ArrayList<String> getAllContacts() {
        SQLiteDatabase db = this.getReadableDatabase();
        ArrayList<String> arrayList = new ArrayList<>();
        
        // เรียงตามชื่อจาก Z ถึง A (Descending)
        Cursor res = db.rawQuery(
            "SELECT * FROM " + CONTACTS_TABLE_NAME + " ORDER BY name DESC", null);
        
        res.moveToFirst();
        while (!res.isAfterLast()) {
            arrayList.add(res.getString(res.getColumnIndex("name")));
            res.moveToNext();
        }
        res.close();
        return arrayList;
    }

    public boolean update(String name, String salary) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL("UPDATE " + CONTACTS_TABLE_NAME + 
            " SET name = '" + name + "', salary = '" + salary + "'");
        return true;
    }

    public boolean delete() {
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL("DELETE FROM " + CONTACTS_TABLE_NAME);
        return true;
    }
}

การทดสอบ

รันแอปพลิเคชัน เพิ่มข้อมูลหลายรายการ แล้วกด Refresh

วิธีแสดงข้อมูลเรียงลำดับ Descending ใน SQLite Android

วิธีแสดงข้อมูลเรียงลำดับ Descending ใน SQLite Android

ผลลัพธ์: แสดงชื่อเรียงลำดับ DESC (Z → A)

วิธีแสดงข้อมูลเรียงลำดับ Descending ใน SQLite Android

ความรู้เพิ่มเติมเกี่ยวกับ ORDER BY

รูปแบบ ORDER BY

-- เรียงคอลัมน์เดียว
ORDER BY column_name ASC      -- น้อยไปมาก (Default)
ORDER BY column_name DESC     -- มากไปน้อย

-- เรียงหลายคอลัมน์
ORDER BY name ASC, salary DESC    -- เรียงชื่อ A-Z, เงินเดือน มากไปน้อย

-- เรียงด้วย Expression/Function
ORDER BY LENGTH(name) DESC        -- เรียงตามความยาวชื่อ
ORDER BY LOWER(name) ASC          -- เรียงไม่สนใจ Case
ORDER BY CAST(salary AS REAL) DESC -- เรียงตัวเลขใน String

NULLS FIRST / NULLS LAST (SQLite 3.38+)

-- ควบคุมตำแหน่ง NULL
ORDER BY name DESC NULLS LAST     -- NULL อยู่ท้าย (Default ใน DESC)
ORDER BY name DESC NULLS FIRST    -- NULL อยู่หน้า

Performance Tips

  • สร้าง Index บนคอลัมน์ที่ใช้ ORDER BY บ่อย
  • CREATE INDEX idx_name ON SalaryDetails(name);
  • Index ช่วยให้ ORDER BY เร็วขึ้นมาก (Index Scan แทน Table Scan + Sort)
  • Compound Index สำหรับ ORDER BY หลายคอลัมน์: CREATE INDEX idx_name_salary ON SalaryDetails(name, salary);

การใช้ LIMIT กับ ORDER BY

-- Top 10 เงินเดือนสูงสุด
SELECT * FROM SalaryDetails ORDER BY CAST(salary AS REAL) DESC LIMIT 10;

-- Pagination (Page 2, 20 items per page)
SELECT * FROM SalaryDetails ORDER BY name ASC LIMIT 20 OFFSET 20;

Collation (การเรียงภาษาไทย)

-- SQLite Built-in Collations
ORDER BY name COLLATE NOCASE ASC    -- ไม่สนใจพิมพ์เล็ก/ใหญ่
ORDER BY name COLLATE RTRIM ASC     -- ตัด Space ท้าย

-- Custom Collation สำหรับภาษาไทย (ต้องใช้ ICU หรือ Extension)
-- ใน Android ใช้ ICU ผ่าน java.text.Collator

Best Practices

  • ระบุ ASC/DESC ชัดเจน เพื่อความอ่านง่าย
  • ใช้ Index สำหรับคอลัมน์ที่ ORDER BY บ่อย
  • รวม WHERE + ORDER BY + LIMIT เพื่อ Performance
  • หลีกเลี่ยง ORDER BY RAND() บนตารางใหญ่ (ใช้วิธีอื่นแทน)
  • ใน Room: ใช้ @Query("SELECT * FROM table ORDER BY name DESC")

สรุป

คำสั่ง ORDER BY column DESC ใช้เรียงข้อมูลจากมากไปน้อย ใช้ร่วมกับ Index จะได้ Performance ดีที่สุด สำหรับภาษาไทยควรพิจารณา Collation ที่เหมาะสม