Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
maxijoey
Člen
Avatar
maxijoey:13.11.2019 11:03

Ahoj,
mám v tabulce sloupec id a name. Je to nějaký varchar 255.
Mohou tam být hodnoty jako:
1 | Háček silný 20mm
2 | Háček silný 25mm
3 | Háček silný 30mm
4 | Háček slabý 10mm
5 | Háček slabý 15mm

Zkusil jsem: V podstatě vím že GROUP_CONCAT udělá co potřebuji, ale nevím jak detekovat tu shodu zleva.
Experimentuji s něčím takovým :
SELECT CASE
WHEN RIGHT(name, 1) THEN
LEFT(name, Length(name) - 2)
ELSE name END,
Group_concat(id_pro­duct)
FROM production_products
GROUP BY 1

ale nedaří se mi to dát do kupy.

Chci docílit: A já bych potřeboval aby mi to Vybralo a grouplo názvy kde je alespon částečná shoda zleva.
To jest výsledek potřebuji takto :
name | id castecne shodných
Háček silný | 1,2,3
Háček slabý | 4,5

 
Odpovědět
13.11.2019 11:03
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13.11.2019 14:21

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/posi­tion/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).

 
Nahoru Odpovědět
13.11.2019 14:21
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13.11.2019 14:25

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)
Editováno 13.11.2019 14:25
 
Nahoru Odpovědět
13.11.2019 14:25
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13.11.2019 14:28
SUBSTRING_INDEX(`sloupec`, ' ', -1) -- to by melo najit mezery a od posledni z nich vse smazat
 
Nahoru Odpovědět
13.11.2019 14:28
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13.11.2019 14:35

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.

Editováno 13.11.2019 14:37
 
Nahoru Odpovědět
13.11.2019 14:35
Avatar
maxijoey
Člen
Avatar
maxijoey:13.11.2019 15:47

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.

 
Nahoru Odpovědět
13.11.2019 15:47
Avatar
maxijoey
Člen
Avatar
maxijoey:13.11.2019 15:49

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.

 
Nahoru Odpovědět
13.11.2019 15:49
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:14.11.2019 8:41

To chce nekoho sikovnejsiho na sql. Mozna to lze delat u fulltextoveho indexu. Netusim.

  • Kazdopadne, ty predem nevis, kolik slov bude stejnych, ale chces to zgrupovat, pokud aspon jedno z nich. V tom pripade staci vybrat prvni slovo nebo odstranit posledni slovo. Coz se da tim substringem, ktery jsem ale netestoval.

SELECT SUBSTRING_INDEX(sloupec, ' ', -1) AS x... GROUP BY x

  • Ale pak budes rikat, ze to nestaci, ze to treba zgrupovat podle max. poctu stejnych slov. Coz lze jedinym zpusobem, ke kazdemu radku najit SELECTem shodu s jakymkoliv dalsim.

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:

  • Vyber vsechny radky
  • Pro kazdy radek vyber opet vsechny radky (krome id aktualniho radku)

-- 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 tento string potom pouzijes pro grupovani prvniho seznamu (protoze jinak bys to nemel podle ceho grupovat). A musi to byt serazene, protoze kazdy radek ti vytvori neco jineho.

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.

 
Nahoru Odpovědět
14.11.2019 8:41
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:14.11.2019 8:54
-- 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.

 
Nahoru Odpovědět
14.11.2019 8:54
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:14.11.2019 9:00

"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.

 
Nahoru Odpovědět
14.11.2019 9:00
Avatar
maxijoey
Člen
Avatar
maxijoey:14.11.2019 9:16

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.

 
Nahoru Odpovědět
14.11.2019 9:16
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 11 zpráv z 11.