Autor Zpráva
tatyalien
Profil *
Dobrý den,
řeším následující problém, mám 2 tabulky, pro příklad: tabulka_zdroj a tabulka_opravena, obě dvě mají sloupce: "SloupecA, SloupecB, SloupecC" v každé jsou data, ale jsou rozdílná. Potřebuji vytáhnout pouze ty změny, ale aby to bralo pouze změny z tabulky opravená. Pro příklad:

tabulka_zdroj obsahuje
a1, a2, a3
c1, c2, c3
b1, b2, b3
d1, d2, d3a
f1, f2, f3

tabulka_opravena obsahuje
A1, a2, a3
c1a, c2, c3
b1, b2, b3
d1, d2, D3a
e1, e2, e3

takže výsledek by měl být:
A1, a2, a3
C1a, c2, c3
d1, d2, D3a
e1, e2, e3

zkoušel jsem příklady z http://www.bitbybit.dk/carsten/blog/?p=71 ale ani jeden mě nepomohl :-( nemáte nějaké řešení? Jednoduché porovnání 2 stejných tabulek, dohledání změn :-( a já na to nemůžu zaboha přijít :(
Přžedem díky za pomoc
tatyalie
TomášK
Profil
Jde nějak poznat odpovídající řádky? Ideálně kdyby tam byl nějaký identifikátor, přes který by to
šlo propojit. Pokud ne, pravděpodobně ho bude potřeba vytvořit ať už přímo v tabulkách nebo uvnitř
dotazu.
Pokud identifikátor není, platí, že n-tý řádek v první tabulce odpovídá n-tému řádku v opravené
tabulce? Nebo tam můžou být i vynechané řádky?
tatyalien
Profil *
v ostré tabulce jsou všechny data stejné typu
a
b
c...

s tím, že jednoznačně identifikované řádky jsou podle 2 sloupcu katalog a cenova hladina. Tabulka neobsahuje žádné id.
Ale do tabulky opravená se přidávají řádky.
tatyalien
Profil *
takže neplatí že 1 řádek je i v druhé tabulce první :-(
tatyalien
Profil *
takže neplatí že 1 řádek je i v druhé tabulce první :-(
tatyalien
Profil *
Příkazem:

Select SloupecA,SloupecB,SloupecC from tabulka_opravena 
UNION 
Select SloupecA,SloupecB,SloupecC from tabulka_zdroj WHERE (SloupecA,SloupecB,SloupecC) not in (select SloupecA,SloupecB,SloupecC FROM tabulka_zdroj)


dostanu už skoro správně data:

SloupecA SloupecB SloupecC
A1 a2 a3
c1a c2 c3
b1 b2 b3 --> až na tento ten tam bejt nemá :-(
d1 d2 D3a
e1 e2 e3
TomášK
Profil
Ten UNION je divný - vezmete všechna data z tabulky opravena a ještě k nim něco přidáte. Nicméně jsem si díky tomu uvědomil, že není nutné k sobě napasovat příslušné řádky, jen to možná bude o něco déle trvat.

Select SloupecA,SloupecB,SloupecC from tabulka_opravena WHERE (SloupecA,SloupecB,SloupecC) not in (select SloupecA,SloupecB,SloupecC FROM tabulka_zdroj)
tatyalien
Profil *
Tohle jsem už myslím zkušel a pro jistotu ještě vyzkoušel a dělá to jednu chybku, zobrazí mě to pouze:

c1a|c2|c3
e1|e2|e3

to nevezme změnu třeba kdyz mám v jedné tabulce hodnotu "a1" a v druhé "A1" tak to nevyhodnotí jako změnu a nevím proč...
tatyalien
Profil *
Nějaké další řešení ;)?
TomášK
Profil
Zajistit, aby porovnávání bylo case sensitive, pomocí COLLATE, viz http://dev.mysql.com/doc/refman/5.0/en/charset-collate.html. Poslední písmenka ja konci jsou buď 'ci' = case insensitive (to je teď), nebo cs = case sensitive (to chcete). Ten zbytek je znaková sada a jazyk, doplňte dle toho, co používáte. Ve výsledku bude něco jako
SELECT ... COLLATE utf_czech_cs
tatyalien
Profil *
utf_czesch_ci mám teď u cs mě to hází chybu:
#1273 - Unknown collation: 'utf8_czech_cs'
TomášK
Profil
Aha, automaticky jsem předpokládal, že bude existovat, ale zřejmě ne. Zkuste utf8_bin.
tatyalien
Profil *
Tak při kódu:

Select SloupecA,SloupecB,SloupecC COLLATE utf8_bin from tabulka_opravena WHERE (SloupecA,SloupecB,SloupecC COLLATE utf8_bin) not in (select SloupecA,SloupecB,SloupecC COLLATE utf8_bin FROM tabulka_zdroj)


To mě vypíše následující:

SloupecA | SloupecB | SloupecC
----------------------------------------
c1a | c2 | c3
d1 | d2 | D3a
e1 | e2 | e3

to je správně, ale ještě to nevzalo hodnotu:
A1 a2 a3 (byla změna z a1 a2 a3)

:-(
TomášK
Profil
Tak jsem se konečně odhodlal, že to vyzkouším, s těmito výsledky:
1, collate je nutné speficikovat pro každý porovnávaný sloupec
SELECT 
    SloupecA,SloupecB,SloupecC 
FROM tabulka_opravena 
WHERE (SloupecA COLLATE utf8_bin, SloupecB COLLATE utf8_bin,SloupecC COLLATE utf8_bin) NOT IN (
        SELECT 
            SloupecA COLLATE utf8_bin,
            SloupecB COLLATE utf8_bin,
            SloupecC COLLATE utf8_bin
         FROM tabulka_zdroj);


2, Nebo lze nastavit defaultní COLLATE pro sloupce v dané tabulce:
CREATE TABLE tabulka_opravena (
    SloupecA VARCHAR(10), 
    SloupecB VARCHAR(10), 
    SloupecC VARCHAR(10)
    ) CHARACTER SET utf8 COLLATE utf8_bin;

jde i nastavení jen pro některé sloupce.

případně převést tabulku na daný COLLATE (možná to jde i někde bez té koverze CHARACTER SETu, ale
neviděl jsem to na první pohled):
ALTER TABLE tabulka_zdroj CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
ALTER TABLE tabulka_opravena CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;


a pak používat jen
 Select SloupecA,SloupecB,SloupecC from tabulka_opravena WHERE (SloupecA,SloupecB,SloupecC) not in (select SloupecA,SloupecB,SloupecC FROM tabulka_zdroj); 


3, Pro jednorázové použití funguje i
Select SloupecA,SloupecB,SloupecC from tabulka_opravena WHERE MD5(CONCAT(SloupecA,SloupecB,SloupecC))not in (select MD5(CONCAT(SloupecA,SloupecB,SloupecC)) FROM tabulka_zdroj);

což je ovšem hodně ošklivé, musíte mít zaručené, že ten kód po vás nikdo nebude číst (ani vy sám) a nikdo vám nekouká přes rameno (a lépe při psaní taky zavřít oči) ;-)
tatyalien
Profil *
Děkuji, všechny verze fungovaly tak jak maj ;)
Děkuji ještě jednou za pomoc.

Ali
Toto téma je uzamčeno. Odpověď nelze zaslat.