Порядок и предел в Go
Порядок в запросе задают через
ORDER BY с именем столбца и
направлением. Так строки приходят
от дешевых к дорогим или наоборот,
а не в случайном порядке вставки.
Предел отрезает хвост результата: после сортировки можно взять только первые несколько строк. Число предела тоже удобно передавать параметром.
Выведем два самых дешевых товара:
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "modernc.org/sqlite"
)
func main() {
os.Remove("shop.db")
db, err := sql.Open("sqlite", "shop.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE goods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
price REAL NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO goods (title, price) VALUES (?, ?)`,
"book", 12.0,
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO goods (title, price) VALUES (?, ?)`,
"pen", 2.0,
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO goods (title, price) VALUES (?, ?)`,
"mug", 9.0,
)
if err != nil {
log.Fatal(err)
}
top := 2
rows, err := db.Query(
`SELECT title, price FROM goods ORDER BY price ASC LIMIT ?`,
top,
)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var title string
var price float64
err = rows.Scan(&title, &price)
if err != nil {
log.Fatal(err)
}
fmt.Println(title, price)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
На экране сначала "pen", затем
"mug". Третья строка не попала
из-за LIMIT.
Для заказов возьмем самые дорогие позиции:
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "modernc.org/sqlite"
)
func main() {
os.Remove("shop.db")
db, err := sql.Open("sqlite", "shop.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
qty INTEGER NOT NULL,
price REAL NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (title, qty, price) VALUES (?, ?, ?)`,
"pen", 2, 2.0,
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (title, qty, price) VALUES (?, ?, ?)`,
"book", 1, 12.0,
)
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(
`SELECT title, price FROM orders ORDER BY price DESC LIMIT ?`,
1,
)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var title string
var price float64
err = rows.Scan(&title, &price)
if err != nil {
log.Fatal(err)
}
fmt.Println(title, price)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
Даны строки goods:
pen 2
mug 9
book 12
Составьте запрос, который вернет одну
самую дорогую строку с полями title
и price.
Нужны три последних по id заказа.
Опишите порядок сортировки и предел
в одном запросе к orders.
Скажите, что изменится, если написать
LIMIT раньше ORDER BY
в тексте запроса.