Giới thiệu
Ví dụ này minh họa cách sử dụng hàm tổng hợp AVG() trong SQLite Android để tính giá trị trung bình của cột số (ví dụ: lương trung bình).
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền đầy đủ thông tin cần thiết.
Bước 2: Thiết kế giao diện (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"
android:orientation="vertical"
tools:context=".MainActivity">
<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">
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Lưu" />
<Button
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tính AVG" />
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cập nhật" />
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Xóa tất cả" />
</LinearLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Bước 3: MainActivity.java
package com.example.andy.myapplication;
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 {
Button save, refresh, update, delete;
EditText name, salary;
ListView listView;
DatabaseHelper helper;
ArrayAdapter arrayAdapter;
ArrayList arrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DatabaseHelper(this);
arrayList = new ArrayList<>(helper.getAllContacts());
name = findViewById(R.id.name);
salary = findViewById(R.id.salary);
listView = findViewById(R.id.listView);
save = findViewById(R.id.save);
refresh = findViewById(R.id.refresh);
update = findViewById(R.id.update);
delete = findViewById(R.id.delete);
arrayAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, arrayList);
listView.setAdapter(arrayAdapter);
delete.setOnClickListener(v -> {
if (helper.deleteAll()) {
Toast.makeText(this, "Đã xóa", Toast.LENGTH_LONG).show();
refreshList();
} else {
Toast.makeText(this, "Xóa thất bại", Toast.LENGTH_LONG).show();
}
});
update.setOnClickListener(v -> {
String n = name.getText().toString().trim();
String s = salary.getText().toString().trim();
if (!n.isEmpty() && !s.isEmpty()) {
if (helper.update(n, s)) {
Toast.makeText(this, "Đã cập nhật", Toast.LENGTH_LONG).show();
refreshList();
} else {
Toast.makeText(this, "Cập nhật thất bại", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Nhập tên");
salary.setError("Nhập lương");
}
});
refresh.setOnClickListener(v -> refreshList());
save.setOnClickListener(v -> {
String n = name.getText().toString().trim();
String s = salary.getText().toString().trim();
if (!n.isEmpty() && !s.isEmpty()) {
if (helper.insert(n, s)) {
Toast.makeText(this, "Đã thêm", Toast.LENGTH_LONG).show();
refreshList();
name.setText("");
salary.setText("");
} else {
Toast.makeText(this, "Thêm thất bại", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Nhập tên");
salary.setError("Nhập lương");
}
});
}
private void refreshList() {
arrayList.clear();
arrayList.addAll(helper.getAllContacts());
arrayAdapter.notifyDataSetChanged();
}
}
Bước 4: 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.SQLiteOpenHelper;
import java.util.ArrayList;
class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "salaryDatabase5";
private static final String TABLE_NAME = "SalaryDetails";
private static final int DATABASE_VERSION = 1;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Dùng REAL hoặc NUMERIC cho số thập phân
String sql = "CREATE TABLE " + TABLE_NAME + " (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, " +
"salary REAL, " + -- REAL cho số thực (float/double)
"datetime DEFAULT CURRENT_TIMESTAMP)";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
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);
try {
cv.put("salary", Double.parseDouble(salary));
} catch (NumberFormatException e) {
cv.put("salary", salary);
}
long result = db.replace(TABLE_NAME, null, cv);
return result != -1;
}
// QUAN TRỌNG: Sử dụng AVG(salary)
ArrayList getAllContacts() {
SQLiteDatabase db = getReadableDatabase();
ArrayList list = new ArrayList<>();
// AVG() bỏ qua giá trị NULL
String query = "SELECT AVG(salary) AS avg_salary FROM " + TABLE_NAME;
Cursor res = db.rawQuery(query, null);
if (res.moveToFirst()) {
double avg = res.getDouble(res.getColumnIndexOrThrow("avg_salary"));
list.add(String.format("Lương trung bình: %.2f", avg));
}
res.close();
return list;
}
boolean update(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
try {
cv.put("salary", Double.parseDouble(salary));
} catch (NumberFormatException e) {
cv.put("salary", salary);
}
int rows = db.update(TABLE_NAME, cv, null, null); // CẢNH BÁO: không WHERE
return rows > 0;
}
boolean deleteAll() {
SQLiteDatabase db = getWritableDatabase();
int rows = db.delete(TABLE_NAME, null, null);
return rows > 0;
}
}
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Nhập vài bản ghi (Lưu), sau đó nhấn Tính AVG.
Kết quả
ListView hiển thị: "Lương trung bình: 7.500.000,00" (ví dụ)
Giải thích AVG() trong SQLite
- AVG(cột): Tính trung bình cộng của các giá trị KHÔNG NULL trong cột
- Kiểu trả về: Luôn là REAL (số thực), ngay cả khi cột là INTEGER
- Bỏ qua NULL: Các hàng có salary = NULL không tính vào trung bình
- Độ chính xác: SQLite dùng double precision (64-bit float)
Các hàm tổng hợp liên quan
| Hàm | Mô tả |
|---|---|
SUM(cột) | Tổng cộng |
AVG(cột) | Trung bình cộng |
MIN(cột) | Giá trị nhỏ nhất |
MAX(cột) | Giá trị lớn nhất |
COUNT(cột) | Số lượng (không NULL) |
COUNT(*) | Số hàng (kể NULL) |
GROUP_CONCAT(cột) | Nối chuỗi các giá trị |
Ví dụ kết hợp:
SELECT
COUNT(*) as total,
AVG(salary) as avg_salary,
MIN(salary) as min_salary,
MAX(salary) as max_salary,
SUM(salary) as total_salary
FROM SalaryDetails;
Lưu ý: Code gốc cột salary khai báo "money" (không chuẩn SQLite). Đã sửa thành REAL. Cũng sửa getDouble() thay vì getString() để format đẹp. Cảnh báo UPDATE không WHERE.