Kenttien lisääminen samaan hakuun MySQL:ssä

SQL

pitäisi joukkueen pistepörssihaku saada tehtyä.
on kaksi taulua (esim. p ja m)
p (kentät id, etunimi, sukunimi):

id|etunimi|sukunimi |
---------------------
1|erkki |esimerkki|
2|pekka |pelimies |


m (kentät aika, tekijä, syöttäjä)

aika|tekijä|syöttäjä|
---------------------
1.00| 1| 2|
2.23| 2| 1|
5.32| 1| 3|

pitäsi saada aikaiseksi haku, jossa on kentät

id|etunimi|sukunimi-|maalit|syötöt|
-----------------------------------
1| erkki|esimerkki| 2| 1|
2| pekka|pelimies | 1| 1|

Tällaisella haulla saan tehtyä hakutuloksen, jossa on muut yllä mainituista paitsi syötöt-sarake:

"SELECT p.id AS id, p.etunimi AS etunimi, p.sukunimi AS sukunimi, COUNT(*) AS maalit FROM p, m WHERE m.tekijä = p.id GROUP BY p.id"

mutta miten samaan hakuun saisi lisättyä muitakin sarakkeita countia käyttäen, esim. tässä tapauksessa tuon syötöt. Miten siis toisen sarakkeen voisi yhdistää tuohon siten, että count-funktion käytössä uudelleen rajaus olisikin "WHERE m.syöttäjä = p.id"

Ja nyt siis nimenomaan tarkoitus olisi saada tehtyä tuo yhdellä haulla enkä halua yhdistellä tietoja jälkeenpäin

14

1567

    Vastaukset 14

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • taulunimi

      en ole mysql:llä tehnyt paljon mitään.
      Mutta jotenkin tällä tapaa...
      select p.id, p.etunimi,p.sukunimi,
      count(em.*) as maalit, count (er.*) as syötöt
      from p, m as em, m as er
      where
      p.id = em.tekija
      and
      p.id = er.syottaja
      group by p.id;

      Huom! en tiedä toimiiko mutta aika lähellä kumminkin. Tarkista tulos jos syöttäjä tiedot puuttuvat, jos ei ole pakollinen tieto. left outer join ehkä mukaan tms.
      Jos et saa tehtyä nii tee näkymät joita vertailet keskenään.

      • Female

        Mikset mene rakennenäkymään, hae näitä kahta taulua sinne ja kaksoiklikkaa niitä tetueita sinne jotka haluat taulukkonäkymään?


    • I.Proqatlis

      Ei tässä tarvita group by –rakennetta ollenkaan.

      Pitää vain tietää, että selectissä voidaan käyttää alikyselyä tähän tapaan:

      select
      p.id,
      p.etunimi,
      p.sukunimi,
      (select count(*) from maalit m where p.id = m.tekija) as tehdyt,
      (select count(*) from maalit m where p.id = m.syottaja) as syötetyt
      from
      pelaajat p;

      Tämä antaa sinulle vastauksen kysymykseesi ! Yksinkertaista :-)

      • SQL

        Tuohan kuulostaa jo todella helpolta.

        Ei ainakaan suoraan näin toiminut, eikä myöskään näin (lisätty AS -sanat):

        select
        p.id,
        p.etunimi,
        p.sukunimi,
        (select count(*) from maalit AS m where p.id = m.tekija) as tehdyt,
        (select count(*) from maalit AS m where p.id = m.syottaja) as syötetyt
        from
        pelaajat AS p


        Virheeksi tulee molemmilla seuraava:

        #1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from maalit m where p.id = m.tekija) as tehdy


      • I.Proqatlis
        SQL kirjoitti:

        Tuohan kuulostaa jo todella helpolta.

        Ei ainakaan suoraan näin toiminut, eikä myöskään näin (lisätty AS -sanat):

        select
        p.id,
        p.etunimi,
        p.sukunimi,
        (select count(*) from maalit AS m where p.id = m.tekija) as tehdyt,
        (select count(*) from maalit AS m where p.id = m.syottaja) as syötetyt
        from
        pelaajat AS p


        Virheeksi tulee molemmilla seuraava:

        #1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from maalit m where p.id = m.tekija) as tehdy

        Hmm. Olen kyllä aivan varma, että tuo kysely toimii MySQL 5.0-versiossa. Minä nimittäin loin kuvaamasi taulut tietokantaan sekä hieman testiaineistoa, ja tulos oli erinomainen.

        Nytkin jos copypastean viestistäni tuon SQL-operaation MySQL Query Browserin kyselyikkunaan, niin se toimii edelleenkin.

        Minulla on myös Aqua Data Studio -käyttöliittymä, ja tätäkin kautta annettuna kysely toimii.

        Saamasi virheilmoitus viittaa siihen, että sinulla käytössä oleva MySQL-versio ei tajua tällaisia alikyselyitä. Itselläni ei ole vanhempia versioita, mutta olen lukenut, että niistä puuttuu koko joukko ominaisuuksia, jotka ovat uusimmassa.

        Tarkista, mikä MySQL-versio sinulla on käytössä ja jos mahdollista, niin päivitä uudempaan.


      • ------
        SQL kirjoitti:

        Tuohan kuulostaa jo todella helpolta.

        Ei ainakaan suoraan näin toiminut, eikä myöskään näin (lisätty AS -sanat):

        select
        p.id,
        p.etunimi,
        p.sukunimi,
        (select count(*) from maalit AS m where p.id = m.tekija) as tehdyt,
        (select count(*) from maalit AS m where p.id = m.syottaja) as syötetyt
        from
        pelaajat AS p


        Virheeksi tulee molemmilla seuraava:

        #1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from maalit m where p.id = m.tekija) as tehdy

        Mikäs MySQL?
        MySQL 5 tukee vasta alikyselyitä, joten MySQL 4.x tuo ei toimine ja taitaa ilmaista asian juuri tuommosella virheilmoituksella. Toki tuon saa toimimaan myös MySQL 4 kunhan vain hajottaa alikyselyt, mut silloin joudut tekemään muutaman kyselyn ja yhdistää tiedot.

        AS ei ole pakollinen joskin sitä kannattaa käyttää selkeyttää, ja yleensä kaik tietokanta käskyt kirjoitetaan isolla näin ne erottaa helpost muista.


        Vaik tuo kysely kuulostaakin helpolta niin SELECT lauseessa olevat alikyselyt ovat aina raskaita ja niitä kannattaa välttää mahdollisuuksien mukaan.


      • ------
        I.Proqatlis kirjoitti:

        Hmm. Olen kyllä aivan varma, että tuo kysely toimii MySQL 5.0-versiossa. Minä nimittäin loin kuvaamasi taulut tietokantaan sekä hieman testiaineistoa, ja tulos oli erinomainen.

        Nytkin jos copypastean viestistäni tuon SQL-operaation MySQL Query Browserin kyselyikkunaan, niin se toimii edelleenkin.

        Minulla on myös Aqua Data Studio -käyttöliittymä, ja tätäkin kautta annettuna kysely toimii.

        Saamasi virheilmoitus viittaa siihen, että sinulla käytössä oleva MySQL-versio ei tajua tällaisia alikyselyitä. Itselläni ei ole vanhempia versioita, mutta olen lukenut, että niistä puuttuu koko joukko ominaisuuksia, jotka ovat uusimmassa.

        Tarkista, mikä MySQL-versio sinulla on käytössä ja jos mahdollista, niin päivitä uudempaan.

        Pyh olit nopeempa :(

        Juu MySQL 4.x puuttu vaik mitä ominaisuuksia kuten alikyselyt, triggerit jne... joiden puuttumisen takia joutu kikkailee vaik miten.

        Version saa selville SELECT VERSION(); kyselyllä.


      • SQL
        ------ kirjoitti:

        Pyh olit nopeempa :(

        Juu MySQL 4.x puuttu vaik mitä ominaisuuksia kuten alikyselyt, triggerit jne... joiden puuttumisen takia joutu kikkailee vaik miten.

        Version saa selville SELECT VERSION(); kyselyllä.

        Jeps. Kiitos kaikille avusta, versio on tosiaankin vain nelonen:

        4.0.27-standard-log

        Täytyypä alkaa pommittaa palveluntarjoajaa, jotta päivittäisi uudempaan...

        Ei kikkailu niin kiinnosta.


      • ------
        SQL kirjoitti:

        Jeps. Kiitos kaikille avusta, versio on tosiaankin vain nelonen:

        4.0.27-standard-log

        Täytyypä alkaa pommittaa palveluntarjoajaa, jotta päivittäisi uudempaan...

        Ei kikkailu niin kiinnosta.

        Leikitkös PHP5:den kanssa?
        Jos niin tällöin on mahollista käyttää SQLiteä, joka taitaa nuo alikyselytkin jne...

        Katsos http://fi.php.net/manual/en/ref.pdo.php ja http://fi.php.net/manual/en/ref.sqlite.php jos mahollista niin PDO kannattaa käyttää tällöin SQLite3 muutoin SQLite 2.84 muistaakseni. Mut molemmat taitaa nuo alikyselyt.

        Vilkaiseppas http://www.personal.fi/ jos ilmainen palveluntarjoaja kiinostaa, siel MySQL5 käytös.


    • I.Proqatlis

      ... systeemin arkkitehtuurista.

      Jos minulla olisi vapaat kädet rakentaa tämä systeemi, niin tekisin näin.

      Lisään pelaajatauluun kentät tehdyt_maalit ja syotetyt_maalit. Nämähän ovat pelaajaan hyvin läheisesti liittyviä tietoja. Aiemmassa versiossa nämä tiedot piti alikyselyillä hakea maalit-taulusta. Jokaisen pelaajan kohdalla kahlattiin maalit-taulu kahdesti läpi etsittäessä tehtyjä ja syötettyjä maaleja. Tässä esittämässäni ratkaisussa nämä tiedot voidaan lukea suoraan pelaajan tiedoista yksinkertaisella selectillä.

      Kuinka saadaan tiedot pelaajataulussa pysymään ajan tasalla? Luon triggerin, joka reagoi uuden rivin lisäämiseen maalit-tauluun. Triggeri päivittää maalin tehneen ja syöttäneen (jos syöttäjä on olemassa) pelaajan tiedot.

      Meillä on siis seuraavat taulut:

      Pelaajat
      ---------
      id
      etunimi
      sukunimi
      tehdyt_maalit
      syotetyt_maalit

      Maalit
      --------
      aika
      tekija
      syottaja


      Triggerin sisältö on tällainen:

      CREATE TRIGGER jengi_teki_maalin AFTER INSERT ON maalit
      FOR EACH ROW
      BEGIN

      UPDATE pelaajat
      SET tehdyt_maalit = tehdyt_maalit 1
      WHERE
      id = NEW.tekija;

      if NEW.syottaja is not null then
      UPDATE pelaajat
      SET syotetyt_maalit = syotetyt_maalit 1
      WHERE
      id = NEW.syottaja;
      end if;

      END


      Mutta kuten aiemmassa viestissä on sanottu, triggerien käyttö vaatii, että MySQL-tietokanta on tasoa 5.

      Pointtini siis on, että arkkitehtuurin suunnittelulla voidaan vaikuttaa paljon siihen, kuinka monimutkaisia ja raskaita SQL-operaatioita systeemissä tarvitaan!

      • tohlo

        > CREATE TRIGGER jengi_teki_maalin
        > AFTER INSERT ON maalit
        > FOR EACH ROW
        > BEGIN
        > UPDATE pelaajat
        > SET tehdyt_maalit = tehdyt_maalit 1
        > ...

        Entä jos maalit-tauluun lisättiin virheellinen rivi, esim. pelaajan id oli virheellinen tai maalia ei hyväksyttykään, vaikka se jo tauluun lisättiin? Laskurisi ei olekaan tällaisten jälkeen enää synkronissa oikean tilanteen kanssa. :)

        Idea kuitenkin sinulla oli se, että tallennetaan koostefunktion (count) tulos tauluunlisäysten yhteydessä, jotta lukumäärää ei aina tarvitse laskea perustietojen avulla uudelleen. Periaatteessa ok idea, mutta tässä täytyy ottaa huomioon kaikki sivuvaikutukset.

        Minä en kovin pienellä datamäärällä lähtisi käyttämään tällaista tallennustapaa. Vasta jos maaleja on tallessa (satoja) miljoonia ja datan määrä oikeasti johtaa siihen, että haut ovat optimoituinakin tehottomia (eikä sovelluskoodin muokkauksella tai taulujen indekseilläkään saada nopeutta), kannattaa alkaa tallennella välituloksia.


      • I.Proqatlis
        tohlo kirjoitti:

        > CREATE TRIGGER jengi_teki_maalin
        > AFTER INSERT ON maalit
        > FOR EACH ROW
        > BEGIN
        > UPDATE pelaajat
        > SET tehdyt_maalit = tehdyt_maalit 1
        > ...

        Entä jos maalit-tauluun lisättiin virheellinen rivi, esim. pelaajan id oli virheellinen tai maalia ei hyväksyttykään, vaikka se jo tauluun lisättiin? Laskurisi ei olekaan tällaisten jälkeen enää synkronissa oikean tilanteen kanssa. :)

        Idea kuitenkin sinulla oli se, että tallennetaan koostefunktion (count) tulos tauluunlisäysten yhteydessä, jotta lukumäärää ei aina tarvitse laskea perustietojen avulla uudelleen. Periaatteessa ok idea, mutta tässä täytyy ottaa huomioon kaikki sivuvaikutukset.

        Minä en kovin pienellä datamäärällä lähtisi käyttämään tällaista tallennustapaa. Vasta jos maaleja on tallessa (satoja) miljoonia ja datan määrä oikeasti johtaa siihen, että haut ovat optimoituinakin tehottomia (eikä sovelluskoodin muokkauksella tai taulujen indekseilläkään saada nopeutta), kannattaa alkaa tallennella välituloksia.

        Kyllä minä olen ottanut huomioon kaikki sivuvaikutukset. Satutko tietämään, että on mahdollista luoda myös sellaisia triggereitä, jotka reagoivat rivillä olevien tietojen päivittämiseen tai koko rivin poistamiseen.

        Jos siis maalin tehnyttä pelaajaa korjataan, niin update-triggeri nuuskii rivillä olleen vanhan ja uuden pelaajan ja suorittaa pelaajatiedoissa olevien laskurien päivitykset.

        Jos koko rivi poistetaan, niin triggeri käy vähentämässä yhden maalin tekijältä ja yhden syöttäjältä (jos sellainen oli).

        Siis triggeritoiminta pitää koko ajan yllä oikeita arvoja pelaajatiedoissa olevissa laskureissa.


      • I.Proqatlis
        tohlo kirjoitti:

        > CREATE TRIGGER jengi_teki_maalin
        > AFTER INSERT ON maalit
        > FOR EACH ROW
        > BEGIN
        > UPDATE pelaajat
        > SET tehdyt_maalit = tehdyt_maalit 1
        > ...

        Entä jos maalit-tauluun lisättiin virheellinen rivi, esim. pelaajan id oli virheellinen tai maalia ei hyväksyttykään, vaikka se jo tauluun lisättiin? Laskurisi ei olekaan tällaisten jälkeen enää synkronissa oikean tilanteen kanssa. :)

        Idea kuitenkin sinulla oli se, että tallennetaan koostefunktion (count) tulos tauluunlisäysten yhteydessä, jotta lukumäärää ei aina tarvitse laskea perustietojen avulla uudelleen. Periaatteessa ok idea, mutta tässä täytyy ottaa huomioon kaikki sivuvaikutukset.

        Minä en kovin pienellä datamäärällä lähtisi käyttämään tällaista tallennustapaa. Vasta jos maaleja on tallessa (satoja) miljoonia ja datan määrä oikeasti johtaa siihen, että haut ovat optimoituinakin tehottomia (eikä sovelluskoodin muokkauksella tai taulujen indekseilläkään saada nopeutta), kannattaa alkaa tallennella välituloksia.

        Sinä epäilit, etten ollut ottanut huomioon kaikkia sivuvaikutuksia. Niinpä esitän kaikki triggerit aivan konkreettisesti MySQL-koodin tasolla. Näet, kuinka triggerit reagoivat kaikkiin muutoksiin.

        Palstan muut lukijat voivat tästä saada ideoita triggerien käyttöön :-)

        1. Se, joka reagoi uuden rivin lisäykseen, on aiemmassa viestissäni.
        2. Triggeri nimeltä hylatty_maali hoitaa päivitykset, jos kirjattu rivi poistetaan.
        3. Triggeri, jonka nimi on tekija_korjaus, käsittelee tapaukset, joissa maalin tekijää tai syöttäjää muutetaan.


        CREATE TRIGGER hylatty_maali AFTER DELETE ON maalit
        FOR EACH ROW

        BEGIN

        UPDATE pelaajat
        SET tehdyt_maalit = tehdyt_maalit - 1
        WHERE id = OLD.tekija;

        if OLD.syottaja is not null then
        UPDATE pelaajat
        SET syotetyt_maalit = syotetyt_maalit - 1
        WHERE id = OLD.syottaja;
        end if;

        END

        * * * * * * * * * * * * * *

        CREATE TRIGGER tekija_korjaus after UPDATE ON maalit
        FOR EACH ROW

        BEGIN

        if NEW.tekija OLD.tekija then
        UPDATE pelaajat
        SET tehdyt_maalit = tehdyt_maalit - 1
        WHERE id = OLD.tekija;

        UPDATE pelaajat
        SET tehdyt_maalit = tehdyt_maalit 1
        WHERE id = NEW.tekija;
        end if;


        if ifnull(NEW.syottaja, 0) ifnull(OLD.syottaja, 0) then

        if OLD.syottaja is not null then
        UPDATE pelaajat
        SET syotetyt_maalit = syotetyt_maalit - 1
        WHERE id = OLD.syottaja;
        end if;

        if NEW.syottaja is not null then
        UPDATE pelaajat
        SET syotetyt_maalit = syotetyt_maalit 1
        WHERE id = NEW.syottaja;
        end if;

        end if;

        END


    • SQL

      Entäs tällainen tilanne:

      kaksi taulua (p ja m)

      p(kentät id, nimi)

      id|nimi |
      -------------
      1|erkki |
      2|pekka |

      m(kentät id, a1, a2)

      id|a1|a2|
      ---------
      1| 2| 2|
      2| 1| 1|
      3| 1| 2|
      4| 2| 3|

      Ja pitäisi saada haku, jossa on seuraavat tiedot:

      id|nimi |a|
      -----------
      1|erkki|2|
      2|pekka|1|

      , jossa siis a sarake on numero 1:sten määrä taulukossa m (erkillä sarakkeessa a1 ja pekalla a2). Kun siis sarakkeessa m.a1 on 2 kappaletta numero 1:stä, niin erkin sarakkeeseen hakutuloksessa tulee 2. Ja pekalla vastaavasti 1.

      Seuraavalla haulla molempien rivien arvoksi tulee 3, joka on siis molemmissa sarakkeissa yhteensä oleva ykkösten määrä. (Mikäli en aivan väärin laskenut)

      SELECT
      p.id AS id,
      p.nimi AS nimi,
      (SELECT count( * ) FROM m WHERE CONCAT('a', p.id) = 1) AS a
      FROM p

      Ymmärrän siis (toivottavasti), mikä tässä on väärin, mutta en osaa kirjoittaa oikeanlaista koodia...

      Ideoita?

    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Mikä on totta mikä ei?

      Onko juoru vai ei että nimeltä mainitsematon henkilö on tehnyt naiselle/naisille jotain joka on väärin?
      Kuhmo
      25
      1888
    2. Lopetetaanko tämä

      Juttu ja mennään eteenpäin? Pystytkö?
      Ikävä
      127
      860
    3. Just saying

      Mies joka antaa naiselle turvallisen olon, on seksikäs. Ei kieroja kikkoja ja haluaa olla vain sen yhden naisen mies.
      Ikävä
      123
      657
    4. Voisin antaa sulle nyt

      Halin❤️
      Ikävä
      54
      598
    5. Löytyikö syy miksi Martina on Muhiksen kanssa

      Saipa naurut Gekkosen kuvasta, missä ovat ravintola Hookissa Immu fight night ottelun jälkeen, Muhoksella pullottaa hirv
      Kotimaiset julkkisjuorut
      90
      555
    6. Tosi kiva on

      Joo. Mitä olisit menettänyt jos olisit paljastanut itsesi?
      Ikävä
      65
      541
    7. Jos selviäisi että kaivattusi

      Olisi savant asperger? Rakastaisitko vielä? Savant-lahjakkuus olisi kapea-alaista neroutta liittyen mekanisiin ja tilan
      Ikävä
      88
      540
    8. Tehdään yhdessä itsestämme

      Parhaat versiot❤️ Se vaatii molemmilta hyvää itsetuntoa!
      Ikävä
      42
      525
    9. Päivän aivopieru Trumpilta

      Trump julisti sodan hyttysiä vastaan. Myös punkit ovat Trumpin sodan kohteena. Eikö vieläkään USA:n kansa tajua tuon uko
      Maailman menoa
      63
      503
    10. Jokin ei täsmää

      Joskus yksi vuosiluku saa katsomaan koko tarinaa uudestaan. Löysin gradun. Matematiikka ei oikein täsmää siihen, mitä mi
      Ikävä
      267
      480
    11. Oliko Jani Halmeen aika jo tippua TTK:sta?

      Jani Halme ja Claudia Ketonen joutuivat jättämään TTK:n. Halme ja Ketonen saivat viimeiseksi jäänestä tanssista, sambas
      Tanssii tähtien kanssa
      26
      474
    12. Janpen Thai lopettanut, miksiköhän

      Hyvää apetta teki.
      Suomussalmi
      9
      466
    13. Toivotko vielä viestiä

      Minulta? En rohkene enää ottaa yhteyttä, kun varmasti jo uusia naisia elämässä. Nolaisin vain itseni.
      Ikävä
      34
      463
    14. Jorma Uotinen läväytti härskin heiton - Paljastus uudesta TTK-romanssista?

      Tuomari Jorma Uotisen linja on välillä hyvinkin rohkea TTK:ssa. Hän näpäytti Jaakko Parkkalille ja Kastanja Rauhalalle v
      Tanssii tähtien kanssa
      9
      439
    15. Kuka kaipaa T m?

      Kerro nainen kirjaimesi vaan... Haluan miettiä kuka tulee ekana mieleeni.. kuin kurkistus tunteiden meren pinnalle, jota
      Ikävä
      31
      435
    16. Miksi jotku naiset on niin tyhmiä

      Että elättelevät turhaa toivoa toisen kustannuksella. Onko ne kaikki kaappilesboja vai mikä niitä vaivaa? Sitten itketä
      Ikävä
      51
      425
    17. Vaikea on tämän

      Jälkeen suhtautua sinuun ilman ettei muista kirjoituksiasi.
      Ikävä
      58
      422
    18. Kerro muuten miksi

      Estit somessa?
      Ikävä
      41
      416
    19. Jätä jo se puolisosi, mun kanssa kilpa-asetelma on tuhoisa.

      Eikä hän tule sitä voittamaan. Myöskään missään vanhassa ei kannata roikkua, koska ei uskalla kohdata muutosta, hyvät as
      Ikävä
      27
      406
    20. S-ryhmän vastuullisuuden kaksoisstandardi

      Vastuullisuuspuhe on helppoa. Vaikeampaa on selittää, miksi S-ryhmän omien merkkien tuotteita ja raaka-aineita hankitaan
      Maailman menoa
      6
      395
    Aihe