MySQL Problem bei Reloadsperre

Gsus

schwankend^^
ID: 215354
L
22 Mai 2006
1.553
68
Hallo,
ich programmiere mir gerade ein kleines Ad-Management Sytem. Mein Problem ist jetzt, die Reloadsperre bei Bannerviews.

Ich habe zwei Tabellen:
global_ads
id |linkurl|bannerurl|views_gebucht|views_abgebaut|klicks_gebucht|klicks_abgebaut|reload|datum

global_ads_reload

id|ip|zeit

Mein Query dafür sieht momentan so aus:
Code:
SELECT 
    `global_ads`.`id`, 
    `global_ads`.`bannerurl` 
FROM 
    `global_ads` 
LEFT JOIN 
    `global_ads_reload` 
    ON (`global_ads`.`id` = `global_ads_reload`.`id`) 
WHERE 
    (
        `global_ads`.`views_gebucht` > `global_ads`.`views_abgebaut` 
        OR 
        `global_ads`.`klicks_gebucht` > `global_ads`.`klicks_abgebaut`
    ) 
    AND  
ORDER BY 
    RAND() 
LIMIT 1
Der AND-Teil des WHERE-Statements ist das, worauf ich absolut nicht komme. Und zwar sollen nur Banner ausgegeben werden, die für den aktuellen User (zu identifizieren über ip) in den letzten x-Sekunden (x entspricht dem feld reload) nicht in der Tabelle global_ads_reload steht.

Ich hoffe ihr versteht das Problem und könnt mir helfen.

mfg
Gsus
 
theoretisch löst es das ja. das problem ist aber, das ich die user nicht grundsätzlich ausschließen will, wenn sie einen banner bereits gesehen haben, wie es in dem beispiel der fall ist, sondern nur für die anzahl der sekunden die im feld reload steht
 
Versuch mal so was:

PHP:
SELECT `global_ads`.`id`, `global_ads`.`bannerurl` 
FROM `global_ads` 
LEFT JOIN `global_ads_reload` 
ON (`global_ads`.`id` = `global_ads_reload`.`id`
AND  `global_ads_reload`.`ip` = ermittelte-IP-Adresse )

WHERE ( 
`global_ads`.`views_gebucht` > `global_ads`.`views_abgebaut` OR 
`global_ads`.`klicks_gebucht` > `global_ads`.`klicks_abgebaut` ) 
AND 
( `global_ads_reload`.`id` IS NULL OR
CURRENT_TIMESTAMP - `global_ads_reload`.`zeit` >  `global_ads`.`reload`
)

ORDER BY RAND() LIMIT 1
 
Versuch mal so was:

PHP:
SELECT `global_ads`.`id`, `global_ads`.`bannerurl` 
FROM `global_ads` 
LEFT JOIN `global_ads_reload` 
ON (`global_ads`.`id` = `global_ads_reload`.`id`
AND  `global_ads_reload`.`ip` = ermittelte-IP-Adresse )

WHERE ( 
`global_ads`.`views_gebucht` > `global_ads`.`views_abgebaut` OR 
`global_ads`.`klicks_gebucht` > `global_ads`.`klicks_abgebaut` ) 
AND 
( `global_ads_reload`.`id` IS NULL OR
CURRENT_TIMESTAMP - `global_ads_reload`.`zeit` >  `global_ads`.`reload`
)

ORDER BY RAND() LIMIT 1
ja :) das sieht so aus als müsste es klappen ;) tuts leider nicht xD ich habe in reload etwas stehen, trotzdem gibt er mir diesen banner immer aus -.- und auch in der reloadtabelle steht meine ip mit zeit und der bannerid -.-
hat noch jemand eine idee? :( muss das feld zeit ein bestimmtes format haben dafür? habe es mit datetime gemacht...
 
muss das feld zeit ein bestimmtes format haben dafür? habe es mit datetime gemacht...
Wenn du DATETIME-Typen hast, kannst du nicht einfach subtrahieren, sondern musst DATE_ADD()/DATE_SUB() verwenden.

Lass dir die relevanten Attribute einfach mit ausgeben und kontrolliere, ob du korrekt rechnest.
 
Wenn du DATETIME-Typen hast, kannst du nicht einfach subtrahieren, sondern musst DATE_ADD()/DATE_SUB() verwenden.
danke.. das funktioniert soweit.. allerdings nur 1x xD heißt: wenn die ip mit dem banner nicht in der db ist, wird der banner angezeigt. dann wird er so lange wie es in reload steht nicht mehr angezeigt, dann aber wieder die ganze zeit, ohne das die reloadzeit erneut 10 sekunden ist..

das gesamte script zum ausgeben der banner sieht so aus:
PHP:
 //Banner aus der Datenbank laden
 $result = $mysql->query("SELECT `global_ads`.`id`, `global_ads`.`bannerurl` FROM `global_ads` LEFT JOIN `global_ads_reload` ON (`global_ads`.`id` = `global_ads_reload`.`id` AND `global_ads_reload`.`ip` = INET_ATON('%s')) WHERE (`global_ads`.`views_gebucht` > `global_ads`.`views_abgebaut` OR `global_ads`.`klicks_gebucht` > `global_ads`.`klicks_abgebaut`) AND (`global_ads_reload`.`id` IS NULL OR (DATE_ADD(`global_ads_reload`.`zeit`, INTERVAL `global_ads`.`reload` SECOND))<NOW()) ORDER BY RAND() LIMIT 1", $_SERVER['REMOTE_ADDR']);
 $banner = mysql_fetch_assoc($result);
 //Views hochzählen
 $result = $mysql->query("UPDATE `global_ads` SET `views_abgebaut` = `views_abgebaut`+1 WHERE `id`=%u LIMIT 1", $banner['id']);
 //Reloadeintrag speichern 
 $result = $mysql->query("INSERT INTO `global_ads_reload` (`id`, `ip`, `zeit`) VALUES (%u, INET_ATON('%s'), NOW())", $banner['id'], $_SERVER['REMOTE_ADDR']);
edit: habe gerade überlegt, dass das daran liegen könnte, dass dann ja 2 reload einträge vorhanden sind.. einer mit abgelaufener relaodsperre und einer mit neuer.. wenn er da dann die abgelaufene nimmt ist das verhalten logisch... also müsste man das eintragen der reloadsperre durch sowas ersetzen:
Code:
 $result = $mysql->query("INSERT INTO `global_ads_reload` (`id`, `ip`, `zeit`) VALUES (%u, INET_ATON('%s'), NOW()) ON DUPLICATE KEY UPDATE `zeit` = NOW()", $banner['id'], $_SERVER['REMOTE_ADDR']);
dabei ist jetzt das porblem, dass es ja praktisch dann eine kombination aus 2 schlüsseln wäre, nämlich ip und id.. geht das dann trotzdem? weil er soll das ja nur ändern, wenn die kombination aus ip und id bereits vorhanden ist..
 
Zuletzt bearbeitet:
dabei ist jetzt das porblem, dass es ja praktisch dann eine kombination aus 2 schlüsseln wäre, nämlich ip und id.. geht das dann trotzdem? weil er soll das ja nur ändern, wenn die kombination aus ip und id bereits vorhanden ist..
Jo das geht, leg den Primär-Index (oder Unique) über beide Felder.
 
Wenn du DATETIME-Typen hast, kannst du nicht einfach subtrahieren, sondern musst DATE_ADD()/DATE_SUB() verwenden.


Selbstverständlich kannst Du zwei TIMESTAMP-Felder subtrahieren. Das Ergebnis ist eine TIME-Duration.

z.B:

PHP:
SELECT  a-b
FROM
( SELECT 
timestamp('2010-02-25 19:32:43') a , 
timestamp('2009-01-17 18:30:43') b ) tabl


ergibt:
PHP:
10108010200.000000

wobei jedesmal zwei Stellen für Jahr , Monat, Tag, Stunde, Minute und Sekunde steht.
Die Differenz ist hier also 1 Jahr, 1 Monat, 8 Tage, 1 Stunden, 2 Minuten und 0 Sekunden

Eine derartige Time-Duration kannst Du übrigens auch wieder zu einem Timestamp dazuaddieren.
 
Es geht zwar um DATETIME, nicht um TIMESTAMP, aber Tatsache, es funktioniert auch da:
Code:
[FONT=Lucida Console]Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.51a-community-nt MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test;
Database changed
mysql> create table foodate (a datetime, b datetime) engine=myisam;
Query OK, 0 rows affected (0.05 sec)

mysql> insert into foodate (a, b) values ('2010-02-25 13:00', '2010-02-25');
Query OK, 1 row affected (0.01 sec)

mysql> select a, b, a-b from foodate;
+---------------------+---------------------+---------------+
| a                   | b                   | a-b           |
+---------------------+---------------------+---------------+
| 2010-02-25 13:00:00 | 2010-02-25 00:00:00 | 130000.000000 |
+---------------------+---------------------+---------------+
1 row in set (0.06 sec)

mysql> drop table foodate;
Query OK, 0 rows affected (0.00 sec)

mysql>[/FONT]
Das wusste ich nicht. Danke für die Aufklärung :)