Autor | Zpráva | ||
---|---|---|---|
slon_cz Profil |
#1 · Zasláno: 3. 6. 2018, 21:21:21
Zdravím, řekněme, že mám číslo 4754 a potřeboval bych z databáze najít všechna čísla, která jsou blízko tomuto číslu, tedy 4854, 3754 atp. v rozmezí max jednohoo čísla pod a nad tím jedním číslem, je to vůbec možné? Zkoušel jsem
'475_%' OR kod LIKE '47_4%' OR kod LIKE '4_54%' OR kod LIKE '_754%' jenže to není moc dobré, potřeboval bych aby to bylo vždy v rozmezí jednoho čísla z těch 4 v řadě. Nějaké nápady na takový regex?
|
||
Kcko Profil |
#2 · Zasláno: 3. 6. 2018, 21:26:46
slon_cz:
Tak si to slož v PHPku a pak si to dosad jako sloupec IN (tvoje hodnoty) |
||
slon_cz Profil |
#3 · Zasláno: 3. 6. 2018, 21:33:18
Ano, v php by to šlo, jen jsem myslel, že by to šlo nějak přímo v sql příkazu přímo :)
|
||
Keeehi Profil |
#4 · Zasláno: 3. 6. 2018, 23:38:26
Bohužel jsi nenapsal, jak se to má chovat v případě rozdílně dlouhých čísel. Jestli to chceš brát spíše jako čísla a doplnit to zleva nulami, nebo to chceš brát více jako řetězce a považuješ to za prefix. Podle toho se pak řeší porovnání. V prvním případě by vzdálenost 1 od čísla 4754 mělo číslo 754, v druhém 475. V mé implementaci je použita první možnost.
DROP FUNCTION IF EXISTS hamming_distance; DELIMITER $$ CREATE FUNCTION `hamming_distance`( i1 INT, i2 INT) RETURNS INT(11) DETERMINISTIC BEGIN DECLARE s1_len, s2_len, i, l, r, d1, d2 INT; DECLARE s1, s2 TEXT; SET s1 = CONVERT(i1, char), s2 = CONVERT(i2, char); SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), i = 1, d1 = 0, d2 = 0; IF s1_len < s2_len THEN SET l = s1_len, r = s2_len - s1_len, d2 = s2_len - s1_len; ELSE SET l = s2_len, r = s1_len - s2_len, d1 = s1_len - s2_len; END IF; WHILE i <= l DO IF SUBSTRING(s1, i + d1, 1) != SUBSTRING(s2, i + d2, 1) THEN SET r = r + 1; END IF; SET i = i + 1; END WHILE; RETURN r; END; $$ DELIMITER ; SELECT * FROM table WHERE hamming_distance(4754, column) = 1; |
||
slon_cz Profil |
Zdravím, to číslo je vždy 4-místné. Při pokusu mi to ovšem hodí chybu
Chyba v dotazu (1366): Incorrect integer value: '' for column 'i2' at row 47 DROP FUNCTION IF EXISTS hamming_distance; DELIMITER $$ CREATE FUNCTION `hamming_distance`( i1 INT, i2 INT) RETURNS INT(11) DETERMINISTIC BEGIN DECLARE s1_len, s2_len, i, l, r, d1, d2 INT; DECLARE s1, s2 TEXT; SET s1 = CONVERT(i1, char), s2 = CONVERT(i2, char); SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), i = 1, d1 = 0, d2 = 0; IF s1_len < s2_len THEN SET l = s1_len, r = s2_len - s1_len, d2 = s2_len - s1_len; ELSE SET l = s2_len, r = s1_len - s2_len, d1 = s1_len - s2_len; END IF; WHILE i <= l DO IF SUBSTRING(s1, i + d1, 1) != SUBSTRING(s2, i + d2, 1) THEN SET r = r + 1; END IF; SET i = i + 1; END WHILE; RETURN r; END; $$ DELIMITER ; SELECT * FROM tabulka WHERE hamming_distance(4754, kod) = 1; |
||
Keeehi Profil |
#6 · Zasláno: 4. 6. 2018, 06:09:25
slon_cz:
„to číslo je vždy 4-místné“ V tom případě ta funkce může být jednodušší DROP FUNCTION IF EXISTS hamming_distance; DELIMITER $$ CREATE FUNCTION `hamming_distance`( i1 INT, i2 INT) RETURNS INT(11) DETERMINISTIC BEGIN DECLARE i, r INT; DECLARE s1, s2 TEXT; SET s1 = CONVERT(i1, char), s2 = CONVERT(i2, char), i = 1, r = 0; WHILE i <= 4 DO IF SUBSTRING(s1, i, 1) != SUBSTRING(s2, i, 1) THEN SET r = r + 1; END IF; SET i = i + 1; END WHILE; RETURN r; END; $$ DELIMITER ; „Chyba v dotazu (1366): Incorrect integer value: '' for column 'i2' at row 47“ To vypadá, jako kdyby jsi ve sloupci kod měl nějakou prázdnou hodnotu -> pak to číslo není vždy 4-místné ale občas 0-místné. Navíc to taky vypadá, že datový typ sloupce kod není číselný ale textový. Pokud se jedná o text, je zbytečné pak uvnitř funkce dělat konverzi. DROP FUNCTION IF EXISTS hamming_distance; DELIMITER $$ CREATE FUNCTION `hamming_distance`( s1 TEXT, s2 TEXT) RETURNS INT(11) DETERMINISTIC BEGIN DECLARE i, r INT; SET i = 1, r = 0; WHILE i <= 4 DO IF SUBSTRING(s1, i, 1) != SUBSTRING(s2, i, 1) THEN SET r = r + 1; END IF; SET i = i + 1; END WHILE; RETURN r; END; $$ DELIMITER ; SELECT * FROM tabulka WHERE hamming_distance('4754', kod) = 1; |
||
Kajman Profil |
#7 · Zasláno: 4. 6. 2018, 09:59:13
slon_cz:
„v rozmezí max jednohoo čísla pod a nad tím jedním číslem“ Rychlejší bude si v php sestavit těch max. 8 řetězců, kterých se to týká, jak radil Kcko. Databáze pak může využít případný index nad tím sloupcem. select * from `tabulka` where `kod` in ('3754', '4654', '4744', '4753', '4755', '4764', '4854', '5754') |
||
Kcko Profil |
#8 · Zasláno: 4. 6. 2018, 10:17:56
Ano přesně tak, nehledě na to, že to v PHP vrstvě zvládneš spíš než modifikovat Keehiho funkci, která vypadá o dost složitěji na pochopení i modifikaci než pár řádků php kódu a roli tam bude hrát samozřejmě i ta rychlost.
|
||
Časová prodleva: 6 let
|
0