Selecteer vanuit tabel maar met unieke waarden.

  • De topic titel is een beetje onduidelijk maar ik hoop dat jullie me wel kunnen helpen.


    Ik ben met een CMS bezig (een vrij groot CMS, en we lopen tegen het einde aan :)). Nu is er iets wat we absoluut niet mogen vergeten: namelijk analytics. Dit doen we o.a. met google analytics en new relic. Maar om de gebruikers van het CMS ook feedback te kunnen geven hoe het met de site gaat zijn we ook een kleine PHP oplossing aan het schrijven.


    Nu is het zo dat bij elke pagina view een set van gegevens de database ingestuurd wordt. Voor deze vraag zijn de velden 'ip' en 'agent' het belangrijkst.


    Nu willen wij een realtime overzicht hebben van actieve gebruikers van de laatste 10 minuten. Echter kom ik er niet helemaal uit hoe ik deze query moet opzetten.


    De bedoeling is dat je met elk ip adres en met elke user agent. Bij elkaar als 1 gebruiker word gezien.
    op het moment dat 1 van deze 2 anders is dan ben je een andere gebruiker.


    Nu moeten we dus een lijst met deze gebruikers uit de database trekken maar het lukt me echt niet.


    De database ziet er uber versimpelt dus zo uit:
    -----------------------
    |id | ip | agent |
    | 1 : 84.. | moz.. |
    -----------------------


    De query die ik op het moment heb:

    SQL
    SELECT * FROM `analytics` where date > date_sub(now(), interval 10 minute) group by agent,ip ORDER BY `id` DESC



    Deze geeft op het moment keurig het goede aantal records weer, maar niet de goede hij geeft me namelijk 2 maal de zelfde terug. Echter klopt de telling wel (dus als ik bijv. op mijn mobiel, en op mijn laptop kijk zegt hij netjes 2, maar laat hij 2 keer mijn laptop zien als return)


    Weet iemand wat ik fout doe? En kan mij eventueel helpen?


    Bij voorbaat dank!

  • Zoals Perry aangeeft kan je DISTRICT gebruiken of je kan REPLACE INTO gebruiken... Natuurlijk ga ik niet het hele script voor je schrijven maar onderstaand een voorbeeld


    Database:

    Code
    CREATE TABLE  `analytics` (
      `ip` varchar(50) NOT NULL,
      `time` datetime NOT NULL,
      PRIMARY KEY (`ip`)
    )


    Update script:

    PHP
    <?php
    $user=$_SERVER['REMOTE_ADDR'];
    $date=date('c');
    mysql_query("REPLACE INTO `analytics` (ip,time) VALUES('$user','$date')");
    ?>


    Ophaal script:

  • Als je niet elke view moet bijhouden, om te weten wat ze bezocht hebben, in die tabel, dan is "replace into" inderdaad perfect.
    Als deze tabel meerdere functies heeft, zoals weten wie wat wanneer heeft bekeken, dan kun je dit niet gebruiken.


    Dan dien je te werken met een DISTINCT mysql query.
    Ik weet niet 100% zeker wat je juist wil, maar dit kan bv al werken:


    SQL
    SELECT DISTINCT ip,agent FROM `analytics` where date > date_sub(now(), interval 10 minute) ORDER BY `id` DESC


    Dan geeft hij gewoon alle unieke combinaties weer van ip en agent.

  • Als je niet elke view moet bijhouden, om te weten wat ze bezocht hebben, in die tabel, dan is "replace into" inderdaad perfect.
    Als deze tabel meerdere functies heeft, zoals weten wie wat wanneer heeft bekeken, dan kun je dit niet gebruiken.


    Dan dien je te werken met een DISTINCT mysql query.
    Ik weet niet 100% zeker wat je juist wil, maar dit kan bv al werken:


    SQL
    SELECT DISTINCT ip,agent FROM `analytics` where date > date_sub(now(), interval 10 minute) ORDER BY `id` DESC


    Dan geeft hij gewoon alle unieke combinaties weer van ip en agent.


    Het idee is dat we wel elke view bij houden. De database structuur voor deze data afhandeling staat al klaar etc.


    Distinct is inderdaad wat ik nodig ga hebben denk ik, echter krijg ik dan alleen de velden ip en agent terug. Terwijl er iets meer velden zijn. Zo ver ik weet is dit niet mogelijk met distinct (of ik heb hem al jaren verkeerd gebruikt)


    Ik denk dat ik het op ga lossen door een extra veld aan te maken waar gewoon het ip, en de agent bijelkaar staan zodat ik maar hoef te scannen naar 1 uniek veld.


    Bedankt iedereen :).


    Betere alternatieven mogen altijd trouwens!

  • GROUP BY is in deze wel de meeste logische keuze, dus wat dat betreft zat je helemaal goed. Ik denk alleen dat je twee foutjes had, de group velden wil je denk ik omdraaien (eerst groeperen op IP, dan op user-agent) en daarnaast moet je de WHERE-clause verplaatsen naar een HAVING clause met een MAX(). Ofwel:


    SQL
    SELECT * FROM analytics GROUP BY ip, agent ORDER BY date HAVING MAX(date) > DATE_SUB(NOW(), interval 10 minute)


    De kolommen samenvoegen is niet echt een goed idee (eerste normaalvorm). Mocht dit niet werken, kun je dan het CREATE TABLE statement met wat INSERT statements met wat voorbeelddata erin posten?

  • Ik heb het probleem opgelost,


    Code
    $db->query('SELECT * FROM `analytics` where domain =:dom AND date > date_sub(now(), interval 10 minute) GROUP BY ip,agent ORDER BY `id` ASC');


    Dat is het geworden, het probleem zat hem namelijk niet in mijn query, maar in de functie waarmee ik de data verwerkte (deze nam huidige user agent data ipv de via de functie meegestuurde (stomme fout :P))

Participate now!

Heb je nog geen account? Registreer je nu en word deel van onze community!