Autor | Zpráva | ||
---|---|---|---|
Pepik1 Profil |
Dobrý den všem, chtěl bych Vás požádat o Vaší pomoc. Řeším jeden příkaz a nevím si sním rady.
Mám tabulku viz níže: id user_id katageie_id value 1 user_1 a 9 2 user_2 a 15 3 user_3 a 6 5 user_1 b 3 6 user_2 b 1 7 user_3 b 1 9 user_1 c 6 10 user_2 c 5 11 user_3 c 2 1) Potřeboval bych docílit toho aby hodnoty z value se seskupily do skupin (a,b,c) a seřadily se od nejmneší po největší v každyý katageiri. user_id a b c user_1 9 3 6 user_2 15 2 5 user_3 6 2 2 2) Seřazená čísla by se nahradila indexem umístění 1=nejmenší; xx=největší. A když budou čísla stejná(jako v kategorii b bude tam index stejný "user_2 i user_3 májí inxex 1", protože mají oba stejné umístění.) user_id a b c user_1 2 2 3 user_2 3 1 2 user_3 1 1 1 3) A nakonec by se prvky v poli user_x(indexy_umístění) sečetli do pole user_x["soucet"] a seřadily od nejmenšího hodnocení po nejvýší. -Požadovaný výstup user_id soucet user_3 3 user_2 6 user_1 7 Budu hrozně moc rád za Vaší pomoc. Předem děkuji |
||
Kajman Profil |
#2 · Zasláno: 18. 5. 2018, 07:12:37
Pro jakou databázi a pro jakou její verzi?
Nebo to chcete počítat v php? A user_1 má dostat za kategorii b dva body nebo tři? Většinou když jsou dvě zlaté mediale, tak se pak dá totiž bronzová a vy tam máte stříbrnou. Pokud jde jen o poslední výsledek a chcete to řešit v databázi, tak si to rozdělení do skupin udělejte do řádků místo sloupců, s tím se jí bude pracovat lépe. |
||
Pepik1 Profil |
Kajman:
1) Jedná se o MYSQL verze 5.6.28. Ale je jedno, jestli se to bude počítat rovnou z DB nebo v php. Jde mi pouze o ten výsledek 2) user_1 má dostat 2 body, je to tak, jak jsem napsal. 3) Ano jde jen o poslední výsledek. Rozepsal jsem to tak jen pro pochopení. Kdyby to šlo udělat nějak jednodušeji, byl bych jedině rád. |
||
Kajman Profil |
#4 · Zasláno: 18. 5. 2018, 09:09:17
Pro tak starou verzi by to to mohlo jít přes temporary tabulku.
CREATE temporary TABLE test_body_tmp AS SELECT user_id, kategorie_id, Min(value) nejmensi FROM test_body GROUP BY user_id, kategorie_id; SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, kategorie_id, (SELECT Count(DISTINCT t2.nejmensi) FROM test_body_tmp t2 WHERE t2.kategorie_id = t1.kategorie_id AND t2.nejmensi <= t1.nejmensi) poradi FROM test_body_tmp t1) r GROUP BY user_id ORDER BY kategorii DESC, soucet Pokud v té tabulce nemůže být více řádků se stejnou kombinací (user_id, kategorie_id), tak ta temporary tabulky potřeba není. |
||
Pepik1 Profil |
Kajman:
Nemůže nastat stejná kombinace. Viz tabulka. id user_id katageie_id value 1 user_1 a 9 2 user_2 a 15 3 user_1 a 9 (todle nastat nemůže) Takže by měl stačit pouze dotaz SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, kategorie_id, (SELECT Count(DISTINCT t2.nejmensi) FROM test_body_tmp t2 WHERE t2.kategorie_id = t1.kategorie_id AND t2.nejmensi <= t1.nejmensi) poradi FROM test_body_tmp t1) r GROUP BY user_id ORDER BY kategorii DESC, soucet A jak poté bude vypadat tedy ten výpis, abych docílil tohoto formátu? user_id soucet 20 3 12 6 6 7 Jinak vážně děkuji moc, za pomoc. |
||
Kajman Profil |
A nestačí tam použít správný název tabulky a sloupečku (value místo nejmensi)?
Sloupeček s počtem kategorií jsem tam dal navíc, abyste mohl kontrolovat, zda měl uživatel záznam pro všechny kategorie. Stačí ho v php nevypsat, ne? |
||
Pepik1 Profil |
#7 · Zasláno: 18. 5. 2018, 10:07:48
Kajman:
Vy jste psal, že by se nemusela používat at Temporary tabulka. Tak jsem myslel, že bych to udělal bez ní a výstup, který potřebuju je. Pole user_1 -> 3 user_3 -> 6 user_2 -> 7 (součet pořadí) Jinak tabulka s kterou pracuji má tyto sloupce id; user_id; katageie_id; value a nazývá se (challenge_result). Prosím pomohl bys mi to teda, dát do kupy? Bohužel se v tomhle moc nevyznám. A jsem Vám vděčný za každou radu. |
||
Kajman Profil |
#8 · Zasláno: 18. 5. 2018, 10:20:19
Stačí v tom dotaze nahradit řetězce test_body_tmp za challenge_result a nejmensi za value. Kdyby to pak házelo chybu, tak ji sem vypište i s tím upraveným dotazem.
|
||
Pepik1 Profil |
Kajman:
Tak jsem to vyzkoušel a neháže to žádnou chybu a ani žádný výsledek. mysql_query("CREATE temporary TABLE test_body_tmp AS SELECT user_id, kategorie_id, Min(value) value FROM challenge_result GROUP BY user_id, kategorie_id;"); $query = mysql_query("SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, kategorie_id, (SELECT Count(DISTINCT t2.value) FROM test_body_tmp t2 WHERE t2.kategorie_id = t1.kategorie_id AND t2.value <= t1.value) poradi FROM test_body_tmp t1) GROUP BY user_id ORDER BY kategorii DESC, soucet"); $user=MySQL_Fetch_Array($query); |
||
Kajman Profil |
#10 · Zasláno: 18. 5. 2018, 13:13:19
Ale vždyť neověřujte výsledek, zda nedošlo k chybě v dotazu...
Některé časteji řešené dotazy pro MySQL - FAQ » Jak si vypsat chybu V prvním dotaze může být problém se středníkem. Pak by spadnul i druhý. Ale pokud tam jsou jedinečné hodnoty, tak tu temporary tabulku nepotřebujete. A mysql_ funkce už nepoužívejte, pište to rovnou v mysqli. Dotaz si navíc můžete vyzkoušet bokem, např. v admineru. |
||
Pepik1 Profil |
#11 · Zasláno: 18. 5. 2018, 13:34:03
Kajman, Pepik1:
Tak středníku jsem si nevšiml a na výpis chyby jsem taky zapoměl. První dotaz píše chybu. Access denied for user 'xx'@'88.86.12%' to database 'yy' Druhý : Query was empty Upravil jsem to taklo, bez té temporary tabulky. $query = mysqli_query("SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, kategorie_id, (SELECT Count(DISTINCT t2.value) FROM challenge_result t2 WHERE t2.kategorie_id = t1.kategorie_id AND t2.value <= t1.value) poradi FROM challenge_result t1) GROUP BY user_id ORDER BY kategorii DESC, soucet"); |
||
Kajman Profil |
#12 · Zasláno: 18. 5. 2018, 13:44:08
Funkce mysqli_query má první parametr identifikátor spojení. Už jste v php někdy s databází pracoval? Jestli ne, nejdříve si o tom něco přečtěte. Ve výsledku to bude rychlejší než nacházet slepé uličky postupem pokus-omyl.
|
||
Pepik1 Profil |
#13 · Zasláno: 18. 5. 2018, 14:09:38
Kajman:
Pracoval, ale s funkci mysqli ne. Nejsem programátor, tak plno věcí neznám, ale chtěl jsem něco vytořit. Jdu na to kouknu. Vždy jsem používal mysql_query. |
||
Taps Profil |
#14 · Zasláno: 18. 5. 2018, 14:34:46
Pepik1:
POkud se nepletu tak princip sql dotazů je stejný jak v mysql tak i v mysqli. |
||
Pepik1 Profil |
#15 · Zasláno: 18. 5. 2018, 15:41:24
Kajman:
$query = mysqli_query($con, "SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, kategorie_id, (SELECT Count(DISTINCT t2.value) FROM challenge_result t2 WHERE t2.kategorie_id = t1.kategorie_id AND t2.value <= t1.value) poradi FROM challenge_result t1) GROUP BY user_id ORDER BY kategorii DESC, soucet"); Stále to píše to samé Query was empty |
||
Kajman Profil |
#16 · Zasláno: 18. 5. 2018, 16:05:42
Tento kód to asi těžko vypisuje. Dotaz v admineru funguje?
|
||
Pepik1 Profil |
#17 · Zasláno: 18. 5. 2018, 17:11:12
Kajman:
Dík moc za ten Adminer, vůbec jsem nevěděl, že něco takového existuje, ale dotaz jsem dal do kupy. SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, exercise_id, (SELECT Count(DISTINCT t2.value) FROM challenge_result t2 WHERE t2.exercise_id = t1.exercise_id AND t2.value <= t1.value) poradi FROM challenge_result t1) r WHERE exercise_id=32 || exercise_id=34 GROUP BY user_id ORDER BY kategorii DESC, soucet Ale potřeboval bych ještě 1 věc. Doplnit do tabulku JOIN Tabulku challenge_result.user_id připojit na tabulku registration.user_id a z tabulky registration bych potřeboval sloupec category_id a Tabulku challenge_result.user_id připojit na tabulku user.id a z tabulky user bych potřeboval sloupec last_name A to bude vše a budu ti vážně vděčný. Zkoušel jsem to, ale nepovedlo se mi to. |
||
Keeehi Profil |
#18 · Zasláno: 18. 5. 2018, 17:23:37
Pepik1:
Nevím, zda je to v tomto případě potřeba ale vždy to celé můžeš vzít jako subdotaz, dát tomu výsledku alias a joinovat na to. SELECT * FROM ( ten původní dotaz ) t3 JOIN registration ON t3.user_id = registration.user_id JOIN user ON t3.user_id = user.id |
||
Pepik1 Profil |
Díky moc
|
||
Kajman Profil |
#20 · Zasláno: 18. 5. 2018, 18:47:16
Jen to order by presuňte až na konec nového dotazu.
|
||
Keeehi Profil |
#21 · Zasláno: 18. 5. 2018, 19:57:02
Kajman:
Fungoval by ten join i v původním dotazu? Jelikož je tam group by podle sloupce podle kterého se dělá join, tak si říkám, že by to mohlo fungovat ale tvrdit si to netroufám. |
||
Kajman Profil |
#22 · Zasláno: 18. 5. 2018, 20:08:47
Asi jo, ale raději bych to takto obalil, aby plánovač mysql měl méně šancí dotaz zpomalit.
|
||
Pepik1 Profil |
Tak nadšení bylo předčasné, nedělá to to co má. Nevíte někdo čím by to mohlo být? I když vyberu pouze 1 kategorii, tak ty součty.
SELECT * FROM ( SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, exercise_id, (SELECT Count(DISTINCT t2.value) FROM challenge_result t2 WHERE t2.exercise_id = t1.exercise_id AND t2.value <= t1.value) poradi FROM challenge_result t1) r WHERE (exercise_id=36 OR exercise_id=34) GROUP BY user_id) t3 JOIN registration ON t3.user_id = registration.user_id JOIN users ON t3.user_id = users.id WHERE category_id=11 ORDER BY soucet |
||
Kajman Profil |
#24 · Zasláno: 18. 5. 2018, 21:32:03
Pokud se to pořadí má určovat jen vůči uživatelům v category_id 11, tak ta podmínka musí být i v tom výpočtu bodů...
SELECT t3.*, users.last_name FROM (SELECT user_id, Sum(poradi) soucet, Count(*) kategorii FROM (SELECT user_id, exercise_id, (SELECT Count(DISTINCT t2.value) FROM challenge_result t2 JOIN registration r2 ON t2.user_id = r2.user_id AND r2.category_id = 11 WHERE t2.exercise_id = t1.exercise_id AND t2.value <= t1.value) poradi FROM challenge_result t1 JOIN registration r1 ON t1.user_id = r1.user_id AND r1.category_id = 11 WHERE exercise_id IN ( 34, 36 )) r GROUP BY user_id) t3 JOIN users ON t3.user_id = users.id ORDER BY kategorii DESC, soucet Když už tam je tolik podmínek, tak se možná přeci jen ta temporary tabulka mohla hodit, aby ten filtr na exercise_id a category_id byl jen jednou. Těžko říci, co bude ryhlejší. Nebo přejít na mariadb 10.2.+, která umí window funkce. |
||
Pepik1 Profil |
Kajman:
Jinak obdivuji tvé znalosti. V Admineru mi to píše chybu. Chyba v dotazu (1052): Column 'user_id' in field list is ambiguous Vyřešeno, snad už to bude šlapat |
||
Kajman Profil |
#26 · Zasláno: 18. 5. 2018, 22:15:56
Asi tam chybělo t1.user_id na řáxku 6, jen jsem dotaz odhadoval :-)
Snad jen jedna věc. Myslel jsem, že méně bodů znamená lépe, ale pokud to jsou naopak nejhorší, tak řaďte dle součtu a počet kategorií, které tam stále cpu, nemá být prvotní řadící kritérium. |
||
Pepik1 Profil |
Už to začíná vypadat, ale furt tam něco nesedí.
Ještě můžu dodat, že sloupec value(varchar) a můžou v něm být 3 typy hodnot Čas(6:01), body(35) nebo body (35,5). Do sloupce "type" doplnuji jestli je to format(Time,number nebo float). když vyberu pouze jednu exercise_id IN ( 34) typu čas, seřadíme se to: 4 (poslední je na 1 místě) 1 2 3 když vyberu pouze jednu exercise_id IN ( 32) typu body(číslo), seřadíme se to: 5 (poslední je na 1 místě) 1 (Ten co má být 1 je na 2 místě 4 3 2 (Ten co má být 2 je na posledním míste a potom už to jde posloupností nahoru. Omlouvám se ty formáty v sloupci value jsem si neuvědomil. Kajman: Je to tak, nesedí to jen u toho nejhrošího, řadího to na 1 místo |
||
Kajman Profil |
#28 · Zasláno: 18. 5. 2018, 23:16:38
Podle řetězce nemůžete správně řadit, protože '2'>'19' a '9:59'>'10:00'!
|
||
Pepik1 Profil |
Kajman:
Aha a řešení? Zkusit to teda přes PHP? Jinak vždy kategorie bude mít stejný formát. Kategorie a (všechny záznamy int) Kategorei b (všechny záznamy time) |
||
Kajman Profil |
Možná bude nejjednodušší přidat do tabulky challenge_result sloupce
value_time value_number value_float (float nebo decimal) Převést z nynějšího varcharu do odpovídajího sloupce dle konfigurace a v ostatních nechal null hodnoty. A při ukládání nových hodnot vždy vyplnit dvě hodnoty - value i value_spravnydatovytyp. Pak stačí místo AND t2.value <= t1.value AND (t2.value_time <= t1.value_time OR t2.value_number <= t1.value_number OR t2.value_float <= t1.value_float) Nebo necháte value a přidáte číslo value_normalized, kde bude číslo pro porovnání (čas převést na sekundy, u desetinných míst udělal posun dle konfigurace nebo použít decimal, pokud je jejich počet omezený). |
||
Téma pokračuje na další straně.
|
0