[SQL] ist das überhaupt möglich? [für experten]

Greggy

Kies-Media.de
ID: 279865
L
27 Juli 2007
578
38
Es geht um optimierung einer anfrage:
ich habe ein sponsorennetz in dem es eine tabelle gibt in der alle werbeformen gespeichert sind, die im werbenetzwerk verfügbar sind, die ungefähr so aussieht

|ID | Werbeform |
|1 | forced-banner|
|2 | paidmail |
|3 | bannerview |
....

usw.

dann habe ich für jede dieser werbeformen eine tabelle, die präfix_werbeform heißt also z.b. präfix_paidmail und folgenden auffbau hat:

|ID | name | übrig | aufendhalt | .... |

jetzt suche ich einen SQL-befehl um die anzahl der kampagnen in meinem werbenetzwerk rauszubekommen:
Gibt es einen solchen SQL-befehl?

aktuell mache ich das mit einer schelife, und frage jede werbeform einzeln ab...was aber nicht besonders effizient ist (habe aktuell 15 werbeformen ==> 15 sql-anfragen+1 um die werbeform-namen erstmal rauszubekommen).

Danke für eure hilfe
 
Ich bezweifle, dass das mit einem einzigen Query schön zu lösen ist. Ich verstehe den Sinn hinter dieser Aufteilung auch nicht ganz. Wenn alle Tabellen dann eh den gleichen Aufbau haben, kann man doch auch direkt den Typ des Eintrags mit in einer einzigen grossen Tabelle speichern und Du entgehst Deinem momentanen Problem.
 
erstmal danke für die schnelle antwort.

die tabellen haben ca 10 spalten gleich also anzahl, aufendhalt usw. plus einige spalten, die werbeformabhängig sind (z.b. haben paidmails eine weitere spalte mailtext oder pagepeels haben 2 spalten für großes und kleines bild usw. ==> sonst wäres ja zu einfach^^)

Mfg greggy
 
Das hängt davon ab, welchen SQL-Dialekt Du verwendest ( DB2 for zOS, DB2 UDB, MySQL , Sybase ... )

Versuchen kannst Du mal folgendes:

SELECT COUNT(*)
FROM
( SELECT 1 FROM präfix_paidmail
UNION ALL
SELECT 1 FROM präfix_bannerview
UNION ALL
SELECT 1 FROM präfix_paidbanner
....
) A ;


wenn Du die Anzahl Kampagnwen pro Werbeform wissen willst, sollte das funktionieren:

SELECT Werbeform, COUNT(*)
FROM
( SELECT 'paidmail' AS Werbeform FROM präfix_paidmail
UNION ALL
SELECT 'bannerview' AS Werbeform FROM präfix_bannerview
UNION ALL
SELECT 'paidbanner' AS Werbeform FROM präfix_paidbanner
....
) A
GROUP BY Werbeform ;
 
Das hängt davon ab, welchen SQL-Dialekt Du verwendest ( DB2 for zOS, DB2 UDB, MySQL ... )

Versuchen kannst Du mal folgendes:

SELECT COUNT(*)
FROM
( SELECT 1 FROM präfix_paidmail
UNION ALL
SELECT 1 FROM präfix_bannerview
UNION ALL
SELECT 1 FROM präfix_paidbanner
....
) A ;

ich habe mysql.

ich kann deine anfrage nicht nutzen, weil ich ja noch gar nicht weiß, welche werbeformen es gibt....also kann ich z.b. noch gar nicht sagen from "FROM präfix_paidmail"

Mfg Greggy
p.s. ich hatte das scohn mal probiert mit select .... from (select ...)
das gibts scheinbar in mysql nicht ...leider
 
ach so, dann habe ich Dich falsch verstanden.
Du willst aus dem Spalteninhalt der einen Tabelle die Tabellennamen ermitteln.
Dann schaffst Du das nicht in einem Statement.
( Würde ich mir aber auch vom logischen Datenmodell her gut überlegen ... )

Da die Anzahl der unterschiedlichen Tabellen ( = Werbeformen ) nicht so häufig schwanken sollten, könnest Du Dir auch eine View definieren, die den SELECT mit den ganzen UNION ALLs enthält. Dann könntest Du den SELECT COUNT(*) auf diese View machen und bräuchtest bei einer neuen Werbeform nur die View anpassen.
( Allerdings kann ich Dir momentan nicht auswendig sagen, ob MySQL einen UNION ALL in der Viewdefinition erlaubt )
 
Zuletzt bearbeitet:
ach so, dann habe ich Dich falsch verstanden.
Du willst aus dem Spalteninhalt der einen Tabelle die Tabellennamen ermitteln.
Dann schaffst Du das nicht in einem Statement.
( Würde ich mir aber auch vom logischen Datenmodell her gut überlegen ... )
dann hab ich mich wohl falsch ausgedrückt. Das datenmodell stammt nicht aus meiner feder :D ... ist aber recht gut, weil man so sehr schnell neue werbefomen integrieren kann.

Da die Anzahl der unterschiedlichen Tabellen ( = Werbeformen ) nicht so häufig schwanken sollten, könnest Du Dir auch eine View definieren, die den SELECT mit den ganzen UNION ALLs enthält. Dann könntest Du den SELECT COUNT(*) auf diese View machen und bräuchtest bei einer neuen Werbeform nur die View anpassen.
( Allerdings kann ich Dir momentan niocht auswendig sagen, ob MySQL einen UNION ALL in der Viewdefinition erlaubt )

das problem ist halt, dass ich das als "baustein" für andere, die das selbe haupt-script nutzen, verwenden möchte, und ich den meisten (nicht programmierern) nicht zumuten möchte/kann, dass die sich selber views basteln.
Ich könnte höchstens deinen "alten" vorschlag nehmen und vorangestellt einen query nach den werbeformen machen, und dann per php eine neue anfrage (nach deinem system von oben) zusammenbasteln ==> komme ich auf insg. 2 querys im vergleich zu aktuell 16...das ist doch schon mal was...

Dann dank ich dir erstmal soweit

P.S. falls dir doch noch was einfällt bin ich ganz ohr^^
 
Zuletzt bearbeitet:
Leider bin ich in mySQL nicht so fit, ( arbeite im z/OS Umfeld ), aber nur so als Gedankengang:
Gibt es eine System-Katalog-Tabelle, in der die aktuelle Anzahl Sätze drinsteht ?
Dann könnte theoretisch auch sowas funktionieren wie:

SELECT SUM(anzahl-zeilen)
FROM SYSCAT.TABLES <- oder wie die Katalogtabelle bei Euch heisst
WHERE tabellenname IN
( SELECT werbeform FROM werbeform-tabelle );
 
sowas hatte ich schon probiert, aber mein mysql sagt das es nicht erlaubt ist einen select befehl innerhalb des from teils zu verwenden.

Mfg Greggy

P.s. du scheinst ja sehr kompetent zu sein....hast du icq oder sowas, weil ich sehr regelmäßig solche optimierungs-probleme hab, wo ich sonst tagelang suche und trotzdem keine lösung finde...?
 
Bei meiner letzten Query ist der SELECT auch nicht in der FROM, sondern in der WHERE-Klausel. Das sollte auch mySQL verstehen.

Sonst alternativ ein INNER JOIN

SEELCT SUM(anzahl-zeilen)
FROM SYSCAT.TABLES A INNER JOIN werbeform-tabelle B
ON A.tabellenname = B.werbeform ;

Beim Datenmodell wäre überlegenswert, die Daten, die immer gleich sind, in einer Tabelle zusammenzufassen und nur die werbeform-spezifischen Daten in separaten Tabellen zu halten.

Also
Basis:
====
ID ! Werbeform ! Anzahl ! Verweildauer ! Vergütung ! ...

und separat z.B.
paid_banner
=========
ID ! Banner-Url ! ...

das würde sicherstellen, dass die ID wirklich eindeutig ist und solche Auswertungen, wie Du sie wünscht, wären mit einem simplen Statement möglich.


Ich habe kein ICQ oder messenger oder sowas. Du kannst mir aber jederzeit hier eine pn schicken.
 

Da liest man dann folgendes:
he number of rows. Some storage engines, such as MyISAM, store the exact count. For other storage engines, such as InnoDB, this value is an approximation, and may vary from the actual value by as much as 40 to 50%. In such cases, use SELECT COUNT(*) to obtain an accurate count.

Also funktioniert das nur, wenn du MyISAM als Storage Engine nimmst.
Ich bezweifle aber, dass dieser Befehl dein Problem löst, weil du immer noch für jede Tabelle eine eigene Abfrage machen musst. Und hier bekommst du viel mehr Ergebnisse als mit einem SELECT COUNT(*) zurückgeliefert.

Es gibt eine Datenbank 'information_schema' mit der Tabelle 'TABLES' in der Daten zu allen Tabellen drin stehen. Da müßte die Abfrage von transversalis eigentlich gehen:
PHP:
SELECT SUM(TABLE_ROWS)
FROM information_schema.TABLES 
WHERE TABLE_NAME IN
( SELECT werbeform FROM werbeform-tabelle );
Das ganze dürfte aber mit den oben genannten Einschränkunge des SHOW TABLE -Befehls verbunden sein.
 
Also funktioniert das nur, wenn du MyISAM als Storage Engine nimmst.
Ich bezweifle aber, dass dieser Befehl dein Problem löst, weil du immer noch für jede Tabelle eine eigene Abfrage machen musst. Und hier bekommst du viel mehr Ergebnisse als mit einem SELECT COUNT(*) zurückgeliefert.
Es würde mich wundern (oder besser gesagt eher erstaunen), wenn etwas anderes als MyISAM verwendet werden würde.
Und aus Doku geht auch hervor, dass folgendes Query durchaus valide ist:
Code:
SHOW TABLE STATUS
WHERE Name IN (
  SELECT werbeform FROM werbefromen
)
Man kriegt dann halt immer noch X Zeilen zurück, die man mittels PHP zusammen zählen muss, aber evtl. erweist sich das auch nochmal als ganz hilfreich und man entgeht dem COUNT(*), was im Gegensatz zu SHOW TABLE STATUS ja direkt auf der Tabelle arbeitet.

Es gibt eine Datenbank 'information_schema' mit der Tabelle 'TABLES' in der Daten zu allen Tabellen drin stehen.
Solange man keinen Server hat, wird man in den seltensten Fällen Zugriff auf diese Tabelle haben. ;)
 
Ok, ich revidiere mich. Machen wir aus seltensten Fällen einfach "öfter als tleilax erwartet hätte". Aber bei allen immer noch nicht, wenn ich mich grad mal so durch die PMAs, die mir so zur Verfügung stehen, durchklicke.
 
Ok, ich revidiere mich. Machen wir aus seltensten Fällen einfach "öfter als tleilax erwartet hätte". Aber bei allen immer noch nicht, wenn ich mich grad mal so durch die PMAs, die mir so zur Verfügung stehen, durchklicke.

Das gibts ja auch erst seit der 5... ;) Da kannste bis zu Mysql 7 warten bis das "alle" Hoster unterstützen. Das ganze gehöhrt aber zum SQL Standard, jedes größer DBMS arbeitet so ähnlich. Das ganze heißt aber überall anders, man will ja schließlich die migration so "einfach" wie möglich gestallten, dass die Kunden gar nicht erst auf die Idee kommen :LOL: Ich finds aber auf jedenfall besser als SHOW schlag_mich_tot.
 
so:
also ich nutze durchgängig MyISAM.
ich habe jetzt alle vorschläge probiert aber alle haben das problem, dass ich weiterhin 2 querys brauche.
Ich werd mich wohl damit abfinden müssen, dass es mit einem query nicht zu schaffen ist.

Ich danke nochmal allen, die bis hierher mitgeholfen haben. Falls doch noch jemand eine idee hat höre ich die natürlich sehr gerne.

Mfg Greggy