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

1450

    Vastaukset

    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. Kotkalainen Demari Riku Pirinen vangittu Saksassa lapsipornosta

      https://www.kymensanomat.fi/paikalliset/8081054 Kotkalainen Demari Riku Pirinen vangittu Saksassa lapsipornon hallussapi
      Kotka
      86
      2331
    2. Olen tosi outo....

      Päättelen palstajuttujen perusteella mitä mieltä minun kaipauksen kohde minusta on. Joskus kuvittelen tänne selkeitä tap
      Ikävä
      18
      2267
    3. Vanhalle ukon rähjälle

      Satutit mua niin paljon kun erottiin. Oletko todella niin itsekäs että kuvittelet että huolisin sut kaiken tapahtuneen
      Ikävä
      19
      1788
    4. Oletko sä luovuttanut

      Mun suhteeni
      Ikävä
      105
      1477
    5. Maisa on SALAKUVATTU huumepoliisinsa kanssa!

      https://www.seiska.fi/vain-seiskassa/ensimmainen-yhteiskuva-maisa-torpan-ja-poliisikullan-lahiorakkaus-roihuaa/1525663
      Kotimaiset julkkisjuorut
      91
      1440
    6. Hommaatko kinkkua jouluksi?

      Itse tein pakastimeen n. 3Kg:n murekkeen sienillä ja juustokuorrutuksella. Voihan se olla, että jonkun pienen, valmiin k
      Sinkut
      163
      1248
    7. Aatteleppa ite!

      Jos ei oltaisikaan nyt NATOssa, olisimme puolueettomana sivustakatsojia ja elelisimme tyytyväisenä rauhassa maassamme.
      Maailman menoa
      257
      1042
    8. Mitä sanoisit

      Ihastukselle, jos näkisitte?
      Tunteet
      63
      953
    9. Onko se ikä

      Alkanut haitata?
      Ikävä
      78
      919
    10. Omalääkäri hallituksen utopia?

      Suurissa kaupungeissa ja etelässä moinen onnistunee. Suuressa osassa Suomea on taas paljon keikkalääkäreitä. Mitenkäs ha
      Maailman menoa
      174
      903
    Aihe