Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Može li ovo bolje?

[es] :: MySQL :: Može li ovo bolje?

[ Pregleda: 1689 | Odgovora: 10 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.telecentro-reversos.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Može li ovo bolje?14.05.2011. u 14:46 - pre 157 meseci
Sistem sa kojim radim (MySQL 5.1/innodb) ima tablu koja ima primarni ključ (bigint) i jedno varchar polje (ima još polja ali nisu bitna u ovom slučaju)

tabla
---------
id - bigint, autoinc
shortname - varchar(255)


Klijent je poželeo da ima samo vrednosti u varchar polju bez ponavljanja. Dakle ako neko stavi vrednost Pera, to ne sme posle da se ponovi.

OK to je bar lako, dodamo jedan unique index. Problem je što stari podaci moraju da prežive a u slučaju da ima duplikata označiti ih na neki način tako da se može dodati unique index pri tome treba ostaviti bar jednu originalnu vrednost od onih koje se ponavljaju. Ako imam 2 vrednosti Pera jedan treba da ostane.

Evo ga upit koji imam trenutno za taj slučaj:

Code:

UPDATE tabla
SET shortname=CONCAT_WS( '_', shortname, CAST(ROUND(RAND()*1000) AS CHAR) )
WHERE (id > 0) AND
EXISTS (
        SELECT l.id,l.shortname
        FROM (SELECT id,shortname FROM tabla) l,
             ( SELECT id, shortname
               FROM tabla
               GROUP BY shortname
               HAVING COUNT(*)>1 
             ) a
        WHERE l.id<>a.id AND l.shortname=a.shortname
      );


I to radi OK. Moje je pitanje može li to bolje? ( (id > 0) je tu zbog mysql workbencha i one provere koju ima)




Tko leti vrijedi
 
Odgovor na temu

Nikola Poša
Backend (PHP) developer
Beograd

Član broj: 173839
Poruke: 1616
*.adsl-a-11.sezampro.rs.



+33 Profil

icon Re: Može li ovo bolje?15.05.2011. u 09:48 - pre 157 meseci
A možda samo ovako nešto:
Code:
UPDATE tabla
SET shortname = CONCAT_WS('_', shortname, id)
WHERE id NOT IN (SELECT id FROM tabla GROUP BY shortname)

To ce da promeni shortname u string oblika "shortname_id", onih unosa koji se ne nalaze u tom setu distinct-ovanih, pošto će taj GROUP BY da agregira rezultat po shortname-u i vratiće samo one id-eve čiji se shortname-ovi razlikuju.
 
Odgovor na temu

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.telecentro-reversos.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Re: Može li ovo bolje?15.05.2011. u 17:27 - pre 157 meseci
Citat:
Nikola Poša: A možda samo ovako nešto:
Code:
UPDATE tabla
SET shortname = CONCAT_WS('_', shortname, id)
WHERE id NOT IN (SELECT id FROM tabla GROUP BY shortname)



Hmm, zanimljiv pristup. Malo ispravljen i modifikovan query koji radi bi izgledao ovako:

Code:

UPDATE tabla
SET shortname = CONCAT_WS('_', shortname, CAST(id AS CHAR))
WHERE (id>0) AND id NOT IN (SELECT id FROM (SELECT id,shortname FROM tabla) a GROUP BY shortname)


Hvala na ideji.
Tko leti vrijedi
 
Odgovor na temu

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.telecentro-reversos.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Re: Može li ovo bolje?15.05.2011. u 17:40 - pre 157 meseci
A sada poređenje.

Upit koji sam postavio u početnom postu se izvršava na tabli sa 695 slogova za 0.11 sekundi. Upit koji je predložio Nikola se nad istom tablom izvršava za 1.03 sekundi. Skoro 10 puta sporije. Ovo je najverovatnije zbog korišćenja IN koji tera bazu da proverava sve ručno slog po slog.

Zbog toga za sada ostajem pri originalnom upitu.

Tko leti vrijedi
 
Odgovor na temu

bogdan.kecman
Bogdan Kecman
"specialist"
Oracle
srbistan

Član broj: 201406
Poruke: 15887
*.31.24.217.adsl2.beograd.com.

Sajt: mysql.rs


+2377 Profil

icon Re: Može li ovo bolje?15.05.2011. u 19:33 - pre 157 meseci
Citat:
kiklop74:Može li ovo bolje?

Citat:
kiklop74: Sistem sa kojim radim (MySQL 5.1/innodb)


moze bolje - predjes na 5.5 :)

elem, sto se tice upita, ne valja ni jedan, ali na zalost nema nekog "dobrog" resenja za takav upit.

sto se tice brzine, neki join umesto in bi bio brzi i od jednog i od drugog resenja .. (left join sa isnull ...)
 
Odgovor na temu

Nikola Poša
Backend (PHP) developer
Beograd

Član broj: 173839
Poruke: 1616
*.adsl-1.sezampro.rs.



+33 Profil

icon Re: Može li ovo bolje?15.05.2011. u 20:04 - pre 157 meseci
A pitam se da li bi mogao da prođe JOIN direktno posle UPDATE klauzule:
Code:
UPDATE tabla t1
INNER JOIN tabla t2 ON t1.shortname = t2.shortname
SET t1.shortname = CONCAT_WS('_', t1.shortname, t1.id)
WHERE t1.id != t2.id

To bi trebalo da spoji tabele po istom shortname-u i plus da iz rezultata ukloni one redove kod kojih se razlikuje id, tako da će update raditi samo nad tim filtriranim result set-om.
 
Odgovor na temu

ivan.a
PHP developer

Član broj: 83976
Poruke: 403
*.dynamic.isp.telekom.rs.



+44 Profil

icon Re: Može li ovo bolje?15.05.2011. u 22:21 - pre 157 meseci
Probaj i ovako (malo ispravljen upit):

Code:
UPDATE tabla as t1
LEFT JOIN tabla as t2 ON t2.shortname = t1.shortname
SET t1.shortname = CONCAT_WS('_', t1.shortname, t1.id)
WHERE t1.id != t2.id AND t1.id is not null

I hope I didn't brain my damage - Homer
if (wife.position == kitchen) {return sandwich};
 
Odgovor na temu

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.telecentro-reversos.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Re: Može li ovo bolje?16.05.2011. u 23:38 - pre 157 meseci
@Nikola

Tvoj query bi bio ekvivalentan ovome:
Code:

SELECT l.id,l.shortname FROM tabla l
INNER JOIN tabla p ON l.shortname=p.shortname
WHERE l.id <> p.id 


I ovo vraca gomilu duplikata

Ako se stavi GROUP BY nema duplikata ali ostaju svi elementi sto je ekvivalentno jednostavnom selectu sa GROUP BY
Code:

SELECT l.id,l.shortname FROM tabla l
INNER JOIN tabla p ON l.shortname=p.shortname
WHERE l.id <> p.id GROUP BY l.id



@Ivan
Tvoj query pretvoren u SELECT se ponasa kao i Nikolin dakle potreban je GROUP BY za uklanjanje duplikata ali na kraju to nije ono sto meni treba:
Code:

SELECT l.id,l.shortname FROM tabla l
LEFT JOIN tabla p ON l.shortname=p.shortname
WHERE l.id <> p.id AND l.id IS NOT NULL


Da li neko uopste proba query pre slanja?
Tko leti vrijedi
 
Odgovor na temu

bogdan.kecman
Bogdan Kecman
"specialist"
Oracle
srbistan

Član broj: 201406
Poruke: 15887
*.31.24.217.adsl2.beograd.com.

Sajt: mysql.rs


+2377 Profil

icon Re: Može li ovo bolje?17.05.2011. u 03:30 - pre 157 meseci
Citat:
kiklop74: @Nikola
Da li neko uopste proba query pre slanja?


99% ovoga sto sam ja do sada video na forumu - NE!

e sada, ako hoces da "probaju pa posalju" olaksas im zivot :D ... napravis im jedan "create table .. insert into ..." da mogu da copy/paste u svoj mysql pa da probaju, ovako radije bustuju broj postova sa idejama i ocekuju da ti probas :D ...

za razliku od 90% op-ova sa slicnim problemom, ti si se bar iscimao da vratis nazad feedback o tome sta su poslali :)

ako pogledas negde iznas mislim da sam napisao u kom pravcu treba da probas da napravis upit (ja sam malo u frci pa ne mogu sad da probam sve to - dok napravim tabele, dok napunim ..) .. dakle svodi se na left join tabele same sa sobom po kriticnom polju i filtriranje duplikata sa isnull (ako radis left join po polju koje hoces da bude unique desna tabela ce imati null vrednost za to polje) ..
(obrati paznju da je pitanje da li ce biti bolje od onog resenja sa exist mada bi trebalo da je brze)

na primer:

priprema
Code:

mysql> use es
Database changed
mysql> create table x (id int auto_increment primary key, a int, b int) engine=myisam;
Query OK, 0 rows affected (3.95 sec)
mysql> insert into x (a,b) values (1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9), (10,10), (3,3), (4,4), (5,5), (6,6);
Query OK, 14 rows affected (0.00 sec)
Records: 14  Duplicates: 0  Warnings: 0
mysql> select a, count(*) c from x group by a having c>1 order by a;
+------+---+
| a    | c |
+------+---+
|    3 | 2 |
|    4 | 2 |
|    5 | 2 |
|    6 | 2 |
+------+---+
4 rows in set (0.00 sec)


dakle duplikata koliko volis :D

ako sam te dobro svatio, ti hoces duplikate:

Code:

mysql> select p.id, p.a as nonunique_values from x p left join x q on p.a=q.a and p.id <> q.id where !isnull(q.a) order by p.id;
+----+------------------+
| id | nonunique_values |
+----+------------------+
|  3 |                3 |
|  4 |                4 |
|  5 |                5 |
|  6 |                6 |
| 11 |                3 |
| 12 |                4 |
| 13 |                5 |
| 14 |                6 |
+----+------------------+
8 rows in set (0.00 sec)

mysql> select p.id, p.a as unique_values from x p left join x q on p.a=q.a and p.id <> q.id where isnull(q.a) order by p.id;
+----+---------------+
| id | unique_values |
+----+---------------+
|  1 |             1 |
|  2 |             2 |
|  7 |             7 |
|  8 |             8 |
|  9 |             9 |
| 10 |            10 |
+----+---------------+
6 rows in set (0.00 sec)


ovakav join bi trebalo da radi znacajno brzi od ... HAVING COUNT(*)>1 ...
 
Odgovor na temu

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.telecentro-reversos.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Re: Može li ovo bolje?17.05.2011. u 16:43 - pre 157 meseci
OK.

Dakle ovo bi bila pročišćena verzija upita.

Code:

SELECT p.id, p.shortname
FROM tabla p 
LEFT JOIN tabla q ON p.shortname=q.shortname AND p.id <> q.id
WHERE q.shortname IS NOT NULL
ORDER BY p.id;


I radi jedino što opet vraća sve duplikate, a ja sam hteo i da preskočim prvi duplikat od svake grupe. No dobro ne može sve...
Tko leti vrijedi
 
Odgovor na temu

bogdan.kecman
Bogdan Kecman
"specialist"
Oracle
srbistan

Član broj: 201406
Poruke: 15887
*.31.24.217.adsl2.beograd.com.

Sajt: mysql.rs


+2377 Profil

icon Re: Može li ovo bolje?17.05.2011. u 16:54 - pre 157 meseci

Code:

SELECT p.id, p.shortname
FROM tabla p 
LEFT JOIN tabla q ON p.shortname=q.shortname AND p.id <> q.id
WHERE q.shortname IS NOT NULL
GROUP BY p.shortname
ORDER BY p.id;


sa group by ti vadi "jedan od" ne znas koji od dva ali generalno te verovatno ne zanima .. (inace u 99% slucajeva sa myisam i innodb ces dobiti "id poslednjeg" ali to nije pravilo) jedino ne mozes group by da gurnes u update, ali ti je svejedno ovaj upit brzi od onog sa having
 
Odgovor na temu

[es] :: MySQL :: Može li ovo bolje?

[ Pregleda: 1689 | Odgovora: 10 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.