Autor Zpráva
petr
Profil *
Dobrý den,

mám tuto strukturu a data v tabulkách:

CREATE TABLE IF NOT EXISTS `article` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `t2_in` varchar(200) CHARACTER SET latin1 NOT NULL,
  `title` varchar(200) DEFAULT NULL,
  `text` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

INSERT INTO `article` (`id`, `t2_in`, `title`, `text`) VALUES
(1, '1,2,3', 'titulek 1', 'text1...'),
(2, '1,4', 'titulek 2', ' text2...');

CREATE TABLE IF NOT EXISTS `tag` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(800) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

INSERT INTO `tag` (`id`, `name`) VALUES
(1, 'první'),
(2, 'druhý'),
(3, 'třetí'),
(4, 'čtvrtý');

Ponechme prosím stranou, že ta struktura je špatně v tom, že sloupec t2_in měl být správně jako vazebná tabulka.

Zajímá mě, proč dotaz:
SELECT *, (SELECT GROUP_CONCAT(tag.name) FROM tag  WHERE id IN (article.t2_in) ) FROM article
vrací vždy pouze první tag a ne všechny, které jsou v t2_in vyjmenované?
Alphard
Profil
Já být návrhář db enginu, vrátím vám nekompromisně null... Vy hledáte číslo ve stringu, tohle '1,2,3' je řetězec, ne seznam. Mysql si to konvertuje na číslo 1 (přečte co může a zbytek zahodí). Když změníte pořadí těch id, bude výsledek odpovídat prvnímu číslu, např. pro '3,2,1' to vrátí 'třetí'.
petr
Profil *
Alphard:
Jenže když si tam manuálně dosadím ty idečka třeba takto:
SELECT *, (SELECT GROUP_CONCAT(tag.name) FROM tag  WHERE id IN (1,2,3) ) FROM article
tak mi to vrátí všechny názvy daných tagů. Vždyť celý SQL dotaz je pořád jen string (i ten vnitřek v IN()), tak proč to při manuálním dosazení funguje a když tam dám hodnoty ze sloupce, které jsou v totožném formátu, tak to nejde?
lionel messi
Profil
petr:
Lenže je rozdiel medzi:

1, 2, 3 (výpočet čísel)

a

'1, 2, 3' (string)
petr
Profil *
lionel messi:
Hm, už to začínám chápat. Převod ze stringu na čísla (něco na způsob split string) MySQL záměrně neobsahuje. Takže když si to tam dosadím přes PHP, tak mi to projde a zázrakem se z toho stane "seznam čísel", zatímco když si to tam dosadím přímo v dotazu, tak mám smůlu.
lionel messi
Profil
petr:
Celý problém vyplýva z toho, že „ta struktura je špatně v tom, že sloupec t2_in měl být správně jako vazebná tabulka“.
petr
Profil *
lionel messi:
Ale to je přeci jedno. Kterou normální formu se rozhodnu dodržovat je snad moje věc. Ten dotaz není z principu špatně, jen to prostě MySQL záměrně sabotuje.
lionel messi
Profil
petr:
Kterou normální formu se rozhodnu dodržovat je snad moje věc.

Treba však počítať s tým, že niektoré zlé návrhy môžu spôsobovať problémy.
Alphard
Profil
petr:
Ten dotaz není z principu špatně, jen to prostě MySQL záměrně sabotuje.
Ale kdepak, svět se proti vám nespiknul, jen nechápete všechny souvislosti. Kdyby se dotaz skutečně vykonal tak, jak vy chcete, docházelo by k vyhodnocení uložených dat jako dotazu, v podstatě ekvivalentu eval. Což by byla (kromě jiného) obrovská bezpečnostní díra.
petr
Profil *
Alphard:
Tak evidentně to MySQL alespoň částečně vyhodnocuje, když je schopné z toho vyseparovat to první číslo, viz [#2] . V IN mají být prostě nějaké hodnoty oddělené čárkami, na tom přece není co vyhodnocovat.
Když použiju
SELECT *, (SELECT GROUP_CONCAT(tag.name) FROM tag  WHERE id = 1 OR id = 2 OR id = 3 )
nebo
SELECT *, (SELECT GROUP_CONCAT(tag.name) FROM tag  WHERE id = nejaky_jiny_sloupec )
tak je to v pohodě. Udělat totéž s IN je ale fuj :-). OK, jsem smířený s tím, že prostě nechápu všechny souvislosti.
juriad
Profil
IN chce čárkami oddělený seznam prvků. Tento seznam může obsahovat i jen jedný prvek. Každý prvek musí být stejného datového typu jako je sloupec, se kterým se porovnává. Není-li, použijí se běžná pravidla pro přetypování. Pro číselný sloupec a řetězec to znamená, že se pokusí z řetězce udělat číslo - hladově - vezme nejdelší začátek řetězce, který lze chápat jako číslo a zbytek zahodí. Toto přetypování se provádí dlouho poté, co se identifikují jednotlivé prvky seznamu.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0