Saya memainkan permainan bola basket yang memungkinkan untuk mengeluarkan statistiknya sebagai file basis data, jadi orang dapat menghitung statistik dari itu yang tidak diterapkan dalam permainan. Sejauh ini saya tidak punya masalah menghitung statistik yang saya inginkan, tetapi sekarang saya mengalami masalah: menghitung jumlah ganda ganda dan / atau tiga kali lipat ganda yang dibuat seorang pemain selama musim ini dari statistik permainannya.
Definisi ganda ganda dan ganda ganda adalah sebagai berikut:
Ganda-ganda:
Double-double didefinisikan sebagai kinerja di mana pemain mengakumulasi total angka dua digit dalam dua dari lima kategori statistik — poin, rebound, assist, mencuri, dan tembakan yang diblokir — dalam sebuah game.
Triple-double:
Triple-double didefinisikan sebagai kinerja di mana pemain mengakumulasi total angka dua digit dalam tiga dari lima kategori statistik — poin, rebound, assist, steal, dan tembakan yang diblokir — dalam sebuah permainan.
Quadruple-double (ditambahkan untuk klarifikasi)
Quadruple-double didefinisikan sebagai kinerja di mana pemain mengakumulasi total angka dua digit dalam empat dari lima kategori statistik — poin, rebound, assist, steal, dan tembakan yang diblokir — dalam sebuah permainan.
Tabel "PlayerGameStats" menyimpan statistik untuk setiap permainan yang dimainkan pemain dan terlihat sebagai berikut:
CREATE TABLE PlayerGameStats AS SELECT * FROM ( VALUES
( 1, 1, 1, 'Nuggets', 'Cavaliers', 6, 8, 2, 2, 0 ),
( 2, 1, 2, 'Nuggets', 'Clippers', 15, 7, 0, 1, 3 ),
( 3, 1, 6, 'Nuggets', 'Trailblazers', 11, 11, 1, 2, 1 ),
( 4, 1, 10, 'Nuggets', 'Mavericks', 8, 10, 2, 2, 12 ),
( 5, 1, 11, 'Nuggets', 'Knicks', 23, 12, 1, 0, 0 ),
( 6, 1, 12, 'Nuggets', 'Jazz', 8, 8, 11, 1, 0 ),
( 7, 1, 13, 'Nuggets', 'Suns', 7, 11, 2, 2, 1 ),
( 8, 1, 14, 'Nuggets', 'Kings', 10, 15, 0, 3, 1 ),
( 9, 1, 15, 'Nuggets', 'Kings', 9, 7, 5, 0, 4 ),
(10, 1, 17, 'Nuggets', 'Thunder', 13, 10, 10, 1, 0 )
) AS t(id,player_id,seasonday,team,opponent,points,rebounds,assists,steals,blocks);
Output yang ingin saya capai terlihat seperti ini:
| player_id | team | doubleDoubles | tripleDoubles |
|-----------|---------|---------------|---------------|
| 1 | Nuggets | 4 | 1 |
Satu-satunya solusi yang saya temukan sejauh ini sangat mengerikan sehingga membuat saya muntah ...; o) ... Sepertinya ini:
SELECT
player_id,
team,
SUM(CASE WHEN(points >= 10 AND rebounds >= 10) OR
(points >= 10 AND assists >= 10) OR
(points >= 10 AND steals >= 10)
THEN 1
ELSE 0
END) AS doubleDoubles
FROM PlayerGameStats
GROUP BY player_id
... dan sekarang Anda mungkin juga muntah (atau tertawa keras) setelah membaca ini. Saya bahkan tidak menulis semua yang diperlukan untuk mendapatkan semua kombinasi ganda ganda, dan menghilangkan pernyataan kasus untuk triple ganda karena itu bahkan lebih konyol.
Apakah ada cara yang lebih baik untuk melakukan ini? Baik dengan struktur tabel yang saya miliki atau dengan struktur tabel baru (saya bisa menulis skrip untuk mengonversi tabel).
Saya dapat menggunakan MySQL 5.5 atau PostgreSQL 9.2.
Berikut ini tautan ke SqlFiddle dengan contoh data dan solusi mengerikan yang saya posting di atas: http://sqlfiddle.com/#!2/af6101/3
Perhatikan bahwa saya tidak benar-benar tertarik pada quadruple-doubles (lihat di atas) karena mereka tidak terjadi dalam permainan yang saya mainkan sejauh yang saya tahu, tetapi itu akan menjadi nilai tambah jika kueri mudah diperluas dengan tanpa banyak menulis ulang ke akun untuk quadruple-dobel.
sumber
CASE
pernyataan karena ekspresi boolean mengevaluasi ke 1 ketika benar dan 0 ketika salah. Saya telah menambahkannya ke jawaban saya di bawah ini dengan berteriak kepada Anda karena tidak dapat memposting blok kode SQL lengkap dalam komentar di sini.CASE
danSUM/COUNT
memungkinkannya untuk bekerja di Postgres juga.CASE
biasanya sedikit lebih cepat. Saya menambahkan demo dengan beberapa perbaikan kecil lainnya.Coba ini (berhasil untuk saya di MySQL 5.5):
Atau bahkan lebih pendek, dengan membohongi kode JChao dari jawabannya, tetapi mengeluarkan
CASE
pernyataan yang tidak dibutuhkan karena boolean expr mengevaluasi menjadi {1,0} ketika {True, False}:Berdasarkan komentar bahwa kode di atas tidak akan berjalan di PostgreSQL karena tidak suka melakukan boolean + boolean. Saya masih tidak suka
CASE
. Inilah jalan keluar di PostgreSQL (9.3), dengan melakukan casting keint
:sumber
=
atau>=
sesuai.CAST(... AS int)
( stackoverflow.com/questions/12126991/… ). MySQL dapat melakukannyaCAST(... AS UNSIGNED)
, yang berfungsi dalam kueri ini, tetapi PostgreSQL tidak bisa. Tidak yakin ada kesamaanCAST
yang keduanya bisa lakukan untuk portabilitas. KASUS Terburuk, mungkin terjebak denganCASE
pada akhirnya jika portabilitas adalah yang terpenting.Inilah satu lagi masalah.
Menurut saya, Anda pada dasarnya bekerja dengan data yang diputar untuk masalah saat ini, jadi hal pertama yang harus dilakukan adalah menghapusnya. Sayangnya PostgreSQL tidak menyediakan alat yang bagus untuk melakukan itu, jadi tanpa masuk ke generasi SQL dinamis di PL / PgSQL, setidaknya kita bisa melakukan:
Ini menempatkan data dalam bentuk yang lebih mudah ditempa, meskipun itu pasti tidak cantik. Di sini saya berasumsi bahwa (player_id, seasonday) cukup untuk mengidentifikasi pemain secara unik, yaitu ID pemain unik di seluruh tim. Jika tidak, Anda harus memasukkan cukup info lain untuk memberikan kunci unik.
Dengan data yang tidak diproteksi itu sekarang mungkin untuk memfilter dan menggabungkannya dengan cara yang bermanfaat, seperti:
Ini jauh dari cantik, dan mungkin tidak secepat itu. Ini dapat dipelihara, membutuhkan perubahan minimal untuk menangani tipe statistik baru, kolom baru, dll.
Jadi ini lebih merupakan "hei, apakah Anda memikirkan" daripada saran yang serius. Tujuannya adalah untuk memodelkan SQL agar sesuai dengan pernyataan masalah secara langsung, daripada membuatnya cepat.
Ini menjadi jauh lebih mudah dengan penggunaan sisipan bernilai multi-waras dan kutipan ANSI dalam SQL berorientasi MySQL Anda. Terima kasih; senang tidak melihat backticks sekali. Yang harus saya ubah adalah pembuatan kunci sintetis.
sumber
explain analyze
kueri merencanakan (atau yang setara dengan MySQL) dan mencari tahu apa yang mereka semua lakukan dan caranya :)Apa yang ditampilkan oleh Yosua untuk MySQL , juga berfungsi di Postgres.
Boolean
nilai dapat dilemparkan keinteger
dan ditambahkan. Para pemerannya perlu eksplisit. Membuat kode yang sangat singkat:SELECT
.Detail dalam jawaban terkait ini.
Namun,
CASE
- meskipun lebih bertele-tele - biasanya sedikit lebih cepat. Dan lebih portabel, jika itu penting:SQL Fiddle.
sumber
Menggunakan pembagian integer dan pemeran biner
sumber
Hanya ingin meninggalkan variasi versi @Craig Ringers di sini yang saya temukan secara tidak sengaja, mungkin berguna bagi seseorang di masa depan.
Alih-alih beberapa UNION ALL itu menggunakan undest dan array. Sumber untuk inspirasi: /programming/1128737/unpivot-and-postgresql
SQL Fiddle: http://sqlfiddle.com/#!12/4980b/3
sumber