Autor Zpráva
danhill
Profil
Ahoj,
chci se zeptat, jak mám správně postupovat.
V php bych použil třeba explode, nebo podobnou funkci,ale potřeboval bych již z databáze vyselectovat jen řádky na základě toho, že jedna z buněk obsahuje hledanou hodnotu.
Konkrétně v jedné z buněk (type) mám uloženu informaci 5,1,6,13,7 a v jiné třeba zase 8,16,4.
Čísla odkazují do jiné tabulky, kde každé číslo je id nějakého servisního úkonu, ale to nyní není podstatné.
A já hledám v tabulce jen řádky, které v této buňce obsahují např. 1 (tedy jen první případ)
Pokud bych použil
SELECT * FROM `service` WHERE `type` LIKE '%1%'
tak mi vypíše logicky i řádek druhý, protože je tam 16.
Má otázka tedy zní, jak správně formulovat takový dotaz, kde hledané číslo v takové buňce je proměnná ?
Děkuji.
Tomášeek
Profil
Mas spatny navrh databaze a toto je jeden z problému.

Oprav si navrh databaze (co hodnota, to radek ve vazební tabulce). Pak bude tento dotaz jednoduchý a předejdes dalším problémum v budoucnu.
danhill
Profil
No, tohle asi nebude úplně jednoduché předělat.
Jedná se o interní web servisní organizace a já potřebuji jen vytáhnout statistiky jednotlivých servisních úkonů u jednotlivých zákazníků za určitá období atp.
Vrhnout se do přepsání logiky ostatních modulů se mi vážně moc nechce, kor když to není moje práce - prostě to tak v minulosti někdo napsal a ten už není ...
A nemyslím si, že ukládání array do buňky je úplně špatně. Viděl jsem to již na několika projektech.
Dokonce i redakční systémy joomla i drupal využívají ukládání array ...
Ale nikdy jsem s tím nepotřeboval pracovat, tak mě to teď trochu zaskočilo ...
To na něco takového mysqli opravdu nemá funkci a musím to prohnat přes php?
Alphard_
Profil *
danhill:
A nemyslím si, že ukládání array do buňky je úplně špatně.
Když chceš vybírat to, co chceš, tak je :)

Dokonce i redakční systémy joomla i drupal využívají ukládání array
Justin Bieber je taky populární, což o kvalitě nic neříká.

Vrhnout se do přepsání logiky ostatních modulů se mi vážně moc nechce
To je zase docela rozumný, ale pouč se z toho.

To na něco takového mysqli opravdu nemá funkci...
Tak prasit jde vždycky, že jo...
where concat(',', `type`, ',') like '%,1,%'

Aby toho sarkasmu nebylo málo, pojmenovat si sloupec reservovaným slovem je další důkaz promyšlenosti :).
danhill
Profil
Chápu samozřejmě - sarkasmus je na místě ...
To je tak, když z původně malých bezvýznamných projektů vznikají firemní portály.
Ten systém je zralý na přepsání komplet. Ale kdo by to dělal/platil, když to funguje,že ...
Mě se to podařilo aspoň všechno přepsat do mysqli ať se vyhnu totalnímu pádu při změně verze php a nové věci můžu psát nově,ale někdy ani to nejde.
Přesto moc děkuji za prasárničku ... zase jsem chytřejší ...:)
danhill
Profil
Uf, tak jsem si nechal poradit a předělal to ...
Ale mám trochu problém s dotazem.
Pomůžete prosím?

Mám čtyři tabulky.
application, service, service_type a spojovací tabulku service_join_type, která slouží k propojení tabulky servis a servis_type.

Z tabulky application chci vypsat všechny aplikace.
Každá aplikace má své id.
Tabulka service obsahuje id, id_application, date_service.
A v tabulce service_join_type jsou sloupce id_sevice a id_type.

A já potřebuji aby výsledný select obsahoval ještě jednu informaci právě z tabulky service.
A sice datum servisního zásahu, jehož id v tabulce service type=22.
Pokud takové datum neexistuje, tak hodnota bude 0 nebo null, to je celkem jedno.

SELECT a.*,c.id_type,b.date_service
FROM application a  
LEFT JOIN service b ON a.id = b.application
LEFT JOIN service_join_type c ON b.id = c.id_service AND c.id_type=22
WHERE a.mj>0

Bohužel tohle nefunguje správně.
Dotaz totiž vypíše mimo požadované datum servisního zásahu id 22 všechny data dané aplikace, tedy aplikace se opakuje.
Kajman
Profil
Mezi b a c zkuste join bez left, celé to zazávorkovat a to s a propojit přes outer join.
danhill
Profil
Ano, taky mám pocit, že možná mám dotaz myšlený dobře,ale ne správně nadefinovaný.
Mohu poprosit o příklad jak to zazávorkovat přes outer ?
Děkuji moc.
Kajman
Profil
Zkusil bych něco jako

SELECT a.*,
       c.id_type,
       b.date_service
FROM   application a
       LEFT JOIN (service b
                  JOIN service_join_type c
                    ON b.id = c.id_service
                       AND c.id_type = 22)
              ON a.id = b.application
WHERE  a.mj > 0
danhill
Profil
Perfektní, moc děkuji ... vypadá, že to chodí ...
Ještě musím pak jednotlive roky vycountovat, ale zkusím to první sám a kdyby mi to nešlo, dovolím si pokračovat v dotaze.
Zatím ještě jednou moc děkuji.
danhill
Profil
Tak to ani netrvalo tak dlouho a jak jsem předpokládal mám problém s countováním.
Dokážu to vypsat zvláště ... Tedy dotaz,kterým vypíšu servisy typu 17 za jednotlivé roky.
SELECT EXTRACT(YEAR FROM a.date_service) AS rok, count(a.id) pocet 
    FROM service a
    LEFT JOIN service_join_type b ON a.id = b.id_service
    WHERE a.date_service>0 AND b.id_type=17
    GROUP BY rok 
    ORDER BY a.date_service DESC
    

Výsledek je pak tabulka asi taková:
|Rok|Pocet|
|2017|3|
|2015|7|
|2013|5|
|2010|9|

Stejně si vypíšu roky a počty u typu servisu 22
Výsledak je pak stejná tabulka s jinými roky a počty:
|Rok|Pocet|
|2017|6|
|2016|4|
|2014|8|
|2010|1|

Tohle je v pořádku,ale nevím, jak udělám dotaz tak, aby mi poslal všechny data najednou.
Tedy aby výstup vypadal asi tak:
|Rok|Pocet(17)|Pocet(22)|
|2017|3|6|
|2016|0|4|
|2015|7|0|
|2014|0|8|
|2013|5|0|
|2010|9|1|

Poradíš prosím ještě? Pak už by to snad mělo být v tomhle ohledu už všechno :)
Děkuji.
Alphard
Profil
danhill [#11]:
Toto (dotaz který má vracet dynamický počet sloupců) snad ani udělat nejde. Nejblíž by mělo být asi:

SELECT EXTRACT(YEAR FROM a.date_service) AS rok, sum(b.id_type = 17) pocet17, sum(b.id_type = 22) pocet22
    FROM service a
    LEFT JOIN service_join_type b ON a.id = b.id_service
    WHERE a.date_service>0
    GROUP BY rok 
    ORDER BY a.date_service DESC
danhill
Profil
super - moc děkuji.
To je, co potřebuji. Ani jsem nechtěl vracet dynamický počet sloupců. Ten je daný.3 sloupce.
Já na to šel jinak:

SELECT EXTRACT(YEAR FROM a.date_service) AS rok, 
    IF(b.id_type=22,count(b.id_type),0) AS pocet22, 
    IF(b.id_type=17,count(b.id_type),0) AS pocet17
    FROM service a
    LEFT JOIN service_join_type b ON a.id = b.id_service
    WHERE a.date_service>0 AND b.id_type=22 OR b.id_type=17
    GROUP BY rok 
    ORDER BY a.date_service DESC

A proto mi to nechodilo ...
Mockrát děkuji!
pcmanik
Profil
danhill:
Len drobnosť namiesto EXTRACT(YEAR FROM a.date_service) AS rok sa to dá zapísať skrátene a myslím že aj čitateľnejšie ako YEAR(a.date_service) AS rok.
A ak rok nepoužívaš v aplikácii tak to rovno môžeš dať do GROUP BY.
Kajman
Profil
Výrazy z where v [#13] kolem OR si zazávorkujte, pak je můžete přidat do podmínky left joinu v [#12].

Pokud ten dotaz budete dělat často a je důležitá rychlost, zvažte přidání indexovaného sloupce rok do tabulky service u databází, které neumí udělat index nad výsledkem funkce.

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: