Diskuze: částečná shoda hodnot
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 11 zpráv z 11.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
Pridej jeden sloupec.nebo dva.
1 | Háček silný 20mm
1 | Háček silný | 20mm
1 | Háček | silný | 20mm
Jakoze seznam kategorii, strom, strukturu
Hacky > silne > 20 mm
Hacky > silne > 30mm
Hacky > slabe > 10 mm
A ty kategorie soupnout pekne do tabulky.
Vsechno ostatni mi prijde slozitejsi.
Asi bys potreboval vytvorit 2 sloupce. Text-posledni slovo, posledni
slovo(text). Slo by to, ale je to spatne (muj nazor).
substring charindex/position/locate reverse/right
SUBSTRING(`sloupec`, 1, LOCATE(' ', REVERSE(`sloupec`)))
REGEXP_REPLACE(`sloupec`, ' [^ ]+$', '') -- nahrad na konci stringu mezeru+znaky_nemezera za ''
RIGHT(`sloupec`, LOCATE(' ', REVERSE(`sloupec`))) -- posledni slovo, asi
-- https://stackoverflow.com/questions/5783145/mysql-sql-query-to-get-last-word-in-text
LOCATE(SUBSTRING_INDEX('Have_a_good_day', '_', -1),'Have_a_good_day')-1 AS indexpos
-- https://stackoverflow.com/questions/12775352/last-index-of-a-given-substring-in-mysql
https://www.tutorialspoint.com/…from-a-field
Nebo regularni vyrazy https://dev.mysql.com/…nctions.html#…
REGEXP Whether string matches regular expression
REGEXP_INSTR() Starting index of substring matching regular expression
REGEXP_LIKE() Whether string matches regular expression
REGEXP_REPLACE() Replace substrings matching regular expression
REGEXP_SUBSTR() Return substring matching regular expression
REGEXP()
Jenze oboji je vypocetne narocne, nevhodne pro grupovani. Kdezto grupovani podle cat_id (4 byte) je asi tak 1000x rychlejsi nez string 20 znaku (20 byte).
Jeste jeden krok jsem vynechal. Jenom to tak z hlavy zkousim, snad si to uz doladis, kdyz budes vedet, jake funkce asi hledat.
x = REVERSE(`sloupec`) -- napis string obracene
y = LOCATE(' ', x) -- najdi prvni mezeru
z = LENGTH(`sloupec`) - y -- odecti od delky stringu
SUBSTRING(`sloupec`, 1, z)
SUBSTRING_INDEX(`sloupec`, ' ', -1) -- to by melo najit mezery a od posledni z nich vse smazat
Hlavne je na tom celem spatne to, ze kdyz to neni kategorie_id (cislo), tak
jako string to muze nekdo zadat takto:
X = tabelator + mezera + nezobrazitelny html znak (v jakemkoliv mnozstvi)
XHáčekXsilnýX20XmmX -- odst. text je 'X'
HáčekXsilnýX20XmmX -- odst. text je 'X'
XHáčekXsilnýX20Xmm -- odst. text je 'Xmm'
HáčekXsilnýX20 mm -- odst. text je ' mm'
HáčekXsilnýXXX20mm -- odst. text je 'X20mm' ale zustane HáčekXsilnýXX a ne
HáčekXsilný
Kdezto s cislem se ti to nemuze stat. Pokud nekdo zada spatne text, tak to proste bude spatne uplne vsude nebo nikde.
Ale to nejsou kategorie, ani nemají být. Jsou to názvy produktu a ty se můžou lišit i několika slovy. Já potřebuji najít všechny řádky co mají nějaké slovo nebo více slov společných zleva. A dohodit si tam sloupec s id těch o které jde. Ten příklad co jsem psal to skoro dělá, ale jen skoro.
Já vycházím z něčeho takového:
http://sqlfiddle.com/#…
ale má to vadu že je to dělaný přesně na případ 1 levé slovo a na konci číslo. Já potřebuji případ vlevo slova a na konci cokoli.
To chce nekoho sikovnejsiho na sql. Mozna to lze delat u fulltextoveho indexu. Netusim.
SELECT SUBSTRING_INDEX(sloupec
, ' ', -1) AS x... GROUP BY x
Hacky > silne > 20 mm
Hacky > silne > 30 mm
Hacky > slabe > 10 mm
Obleceni > bundy > pro zeny > adidas ... To jsou jasne kategorie.
Otazkou je, k cemu je dobra tabulka, kde najdes prvni slovo stejne? Chces
zjistit unikatni zbozi? A co kdyz nekdo poradi slov otoci? Pak by to byl dotaz
typu
'Hacky' IN ('Hacky', 'silne', '20', 'mm') -- string rozsekany podle mezer a
hledas v nem slovo, to je lepsi asi fulltext index, navic by si to umelo asi
poradit s velkymi malymi pismeny, mezerami navic, diakritikou
Nevim, zatim mi to vychazi tak, ze budes muset oddelit unikatni cast zbozi od
zbytku rucne. Protoze nemas jasnou definici, co z toho je unikatni. Rikas, ze
posledni slovo to neni. Take to nemusi byt zadne. Nebo jen prvni slovo. A tu
unikatni cast bych dal do sloupce zvlast, dal ji id jako cele kategorie a podle
ni bych to grupoval.
Jinak bys musel mit nejakou funkci, ktera hleda rozdily v textu, v linuxu je to
diff (program). Urcite to jde v sql napsat, nebo se da najit. V Total comanderu
je funkce porovnej 2 oznacene soubory a najdi v nich rozdily.
google = different of string mysql
STRCMP()
https://dev.mysql.com/…nctions.html
https://stackoverflow.com/…tring-fields
SELECT CONCAT(IF(aa.first_string!=aa.first_string1,first_string,''),
IF(aa.middle_string!=aa.middle_string1,middle_string,'') ,
IF(aa.last_string!=aa.last_string1,last_string,'') ) AS first_result,
CONCAT(IF(aa.first_string!=aa.first_string1,first_string1,''),
IF(aa.middle_string!=aa.middle_string1,middle_string1,'') ,
IF(aa.last_string!=aa.last_string1,last_string1,'') ) AS second_result
FROM (SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`old`, ',', 1), ',', -1)
AS first_string,
IF( LENGTH(`old`) - LENGTH(REPLACE(`old`, ',', ''))>1,
SUBSTRING_INDEX(SUBSTRING_INDEX(`old`, ',', 2), ',', -1) ,NULL) AS middle_string,
SUBSTRING_INDEX(SUBSTRING_INDEX(`old`, ',', 3), ',', -1) AS last_string,
SUBSTRING_INDEX(SUBSTRING_INDEX(`new`, ',', 1), ',', -1) AS first_string1,
IF( LENGTH(`old`) - LENGTH(REPLACE(`new`, ',', ''))>1,
SUBSTRING_INDEX(SUBSTRING_INDEX(`new`, ',', 2), ',', -1) ,NULL) AS middle_string1,
SUBSTRING_INDEX(SUBSTRING_INDEX(`new`, ',', 3), ',', -1) AS last_string1
FROM try ) aa
Algoritmus bych videl nasledujici:
-- porovnej slovo po slove, zapis pocet shod, treba 6, 6, 5, 5, 4, 4, 3, 3,
3, 3, 3, 2, ... 1... 0
-- vyber vsechny radky, kde pocet shod je max, treba 6, 6
-- pridej k tomu id aktualniho radku
-- serad podle id radku
-- vytvor z id radku string '1, 12, 35'
A cely ten sql dotaz muze nejaky casek trvat, protoze pracujes se stringy a jeste ty stringy musis rozdelovat. Cili, nemas nad tim uz index. Neni index, cele se to zpomaluje. Kdybys slova mel v tabulce ulozene, muzes nad nimi udelat indexy.
-- http://www.mysqltutorial.org/mysql-string-functions/mysql-right-function/
SET @str = '12/31/2019';
SELECT
RIGHT(@str, 4) year,
LEFT(@str, 2) month,
SUBSTRING(@str, 4, 2) day;
RIGHT(@str, 4) - vezmi 4 zprava '2019'
LEFT(@str, 2) - vezmi 2 znaky zleva '12'
SUBSTRING(@str, 4, 2) - vezmi od pozice 4 dva znaky '31'
pro substring je to cislovano
12/31/2019
123456789
od pozice 4 je 31/2019
SELECT CASE
WHEN RIGHT(nombre, 1) BETWEEN '0' AND '9' THEN -- kdyz posledni znak mezi 0-9
LEFT(nombre, Length(nombre) - 2) -- smaz posledni znak
ELSE nombre -- nebo nechej cely string
END AS nombrechecked,
Group_concat(id_grupo)
FROM grupos
GROUP BY 1
To mi vysvetli, jak ti tohle muze delat, to, co chces? Bud nehapes, co ty funkce delaji a
pak je to nad tve sily dat dohromady. A nebo potrebujes neco jineho, nez si
myslim.
"a tento string potom pouzijes pro grupovani"
Mozna by misto grupovani slo pouzit DISTINCT SELECT. Pokud k tomu nepridas nic
neunikatniho, tak te zbavi duplicit.
použití toho co chci je pro produkty co mám v tabulce načítané z xml
feedu. V podstatě jde o produkty respektive varianty produktů kde není
žádný klíč dle kterého je spojit do jednoho produktu než tak že mají
shodný kus názvu, většinou třeba prvních 3-5 slov a pak je to rozílné
1-2 slova. Proto to potřebuji.
Ten poslední příklad je právě stavěn na něco trochu jiného, říkám že
z něj jen vycházím, ten počítá s tím že na konci je mezera a jedno
číslo. Ale jinak dělá naprosto přesně to co potřebuji.Když si to
prohlédneš uvidiš.
Dole jsou vypsané fráze a vedle indexy jejich
Jen jsem ho upravoval vlevo nejsou tam ty čísla ale písmena s místo
nich.
Na obrázku je vidět co udělá u mě. Můžu odebrat i ten betwen a udělá to
samé. Jen když se podíváš první dva řádky ok, ale poslední čtyři ne,
ty bych potřeboval aby to taky takto zpracovalo.
Zobrazeno 11 zpráv z 11.