1 oder 2 Queries nötig?
Anton
- datenbank
Guten Tag Forum,
sagen wir es gibt 2 Tabellen.
Tabelle1: Freunde
id |vorname |nachname
1 Jürgen Samser
2 Franz Bäcker
Tabelle2: Email Kontaktdaten
id | email | tel | ort
1 | blah@blah.com | 919191 | büro
1 | bloh@boh.com | 927882 |zuhause
2 |bih@blih.com |928374| büro
2 |kjhfl|jksh.com |92837| büro
Kann man mit einem Select query alle Freunde ausgeben lassen UND auch zu jedem Freund gleichzeitig alle Email Adressen ? Oder benötigt man dazu 2 Queries ?
Hello,
Kann man mit einem Select query alle Freunde ausgeben lassen UND auch zu jedem Freund gleichzeitig alle Email Adressen ? Oder benötigt man dazu 2 Queries ?
Man kann.
Abr siehe den Thread über Deinem.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
hi,
Man kann.
Abr siehe den Thread über Deinem.
in einem forum, wo die threads nicht chronologisch geordnet bleiben, sondern je nach antwortfrequenz nach unten wandern, nicht die hilfreichste aller antwortformen :-)
ein link wäre schön, insb. auch in hinsicht auf die spätere nutzbarkeit im archiv.
spätestens _da_ dürfte der "thread über deinem" nicht mehr so ganz trivial auffindbar sein ...
gruß,
wahsaga
Hello,
Aber siehe den Thread über Deinem.
in einem forum, wo die threads nicht chronologisch geordnet bleiben, sondern je nach antwortfrequenz nach unten wandern, nicht die hilfreichste aller antwortformen :-)
ein link wäre schön, insb. auch in hinsicht auf die spätere nutzbarkeit im archiv.
spätestens _da_ dürfte der "thread über deinem" nicht mehr so ganz trivial auffindbar sein ...
Ach so, das calif "classic automatic link intelligence feature" hat CK noch nicht erfunden?
Gut. ich bezog mich auf https://forum.selfhtml.org/?t=91535&m=550722
Da ging es um Gruppenbildung in der DB, die dadurch anfallende Datenmenge, und/oder Gruppensuche+Auswertung mittels Abfrage-API (hier PHP).
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hallo,
sagen wir es gibt 2 Tabellen.
Tabelle1: Freunde
id |vorname |nachname
1 Jürgen Samser
2 Franz BäckerTabelle2: Email Kontaktdaten
id | email | tel | ort
1 | blah@blah.com | 919191 | büro
1 | bloh@boh.com | 927882 |zuhause
2 |bih@blih.com |928374| büro
2 |kjhfl|jksh.com |92837| büroKann man mit einem Select query alle Freunde ausgeben lassen UND auch zu jedem Freund gleichzeitig alle Email Adressen ? Oder benötigt man dazu 2 Queries ?
Das ist ein klassisches INNER JOIN. Siehe Doku zu Deinem Datenbank-System.
SELECT Freunde.vorname, Freunde.nachname, Kontaktdaten.email FROM Freunde INNER JOIN Kontaktdaten ON Freunde.id = Kontaktdaten.id
Ergibt 4 Datensätze:
Freunde.vorname Freunde.nachname Kontaktdaten.email
Jürgen Samser blah@blah.com
Jürgen Samser bloh@boh.com
Franz Bäcker bih@blih.com
Franz Bäcker kjhfl|jksh.com
viele Grüße
Axel
yo,
Das ist ein klassisches INNER JOIN. Siehe Doku zu Deinem Datenbank-System.
SELECT Freunde.vorname, Freunde.nachname, Kontaktdaten.email FROM Freunde INNER JOIN Kontaktdaten ON Freunde.id = Kontaktdaten.id
das ist eventuell ein klassischer trugschluß, da es sich höchst wahrscheinlich um einen outer join handelt, nämlich genau dann, wenn nicht jeder auch eine email-adresse haben muß.
Ilja
das ist eventuell ein klassischer trugschluß, da es sich höchst wahrscheinlich um einen outer join handelt, nämlich genau dann, wenn nicht jeder auch eine email-adresse haben muß.
nicht outer, LEFT
Kann man mit einem Select query alle Freunde ausgeben lassen UND
yo,
nicht outer, LEFT
das macht mich einfach nur sprachlos....was ist den deiner meinung nach ein LEFT oder von mir aus auch RIGHT JOIN ?
Ilja
das macht mich einfach nur sprachlos....was ist den deiner meinung nach ein LEFT oder von mir aus auch RIGHT JOIN ?
das gabs auch schon zig-fach hier im forum:
ein left join liest die linke tabelle (hier freunde) komplett ein.
ein right join dementsprechend die rechte tabelle.
die vorhandenen zeilen der anderen tabelle werden dazugestellt. wenns keine gibt, gibts null.
der outer join gibt beide tabellen komplett.
obwohl left und right auch als left outer und right outer join gbezeichnet werden, meint ein nur outer immer einen full-outer join.
sagen wir es gibt 2 Tabellen.
Tabelle1: Freunde
id |vorname |nachname
1 Jürgen Samser
2 Franz BäckerTabelle2: Email Kontaktdaten
id | email | tel | ort
1 | blah@blah.com | 919191 | büro
1 | bloh@boh.com | 927882 |zuhause
2 |bih@blih.com |928374| büro
2 |kjhfl|jksh.com |92837| büro
Freunde.vorname Freunde.nachname Kontaktdaten.email
Jürgen Samser blah@blah.com
Jürgen Samser bloh@boh.com
Franz Bäcker bih@blih.com
Franz Bäcker kjhfl|jksh.com
Das ist genau das Problem. Ich nutze eine Schablone. Diese soll in einer Tabelle die Freunde ausgeben(jede Reihe ein Freund.)
So wie es oben zurückgeliefert wird, bekomme man aber Probleme bei der Ausgabe. Wie soll ich so einen Freund beschreiben? So bekommt der Freund in der HTML Tabelle 2 Reihen, je nach Anzahl der Email Adressen. Vielleicht hatte ich mich falsch ausgedrückt. Das ist mein Hauptunverständnis. Wie ist das zu lösen ? War schon wieder fast drauf und dran die beiden Email Adressen in ein Feld einer Zeile zu schreiben und durch Komma zu trennen.
Hallo,
Freunde.vorname Freunde.nachname Kontaktdaten.email
Jürgen Samser blah@blah.com
Jürgen Samser bloh@boh.com
Franz Bäcker bih@blih.com
Franz Bäcker kjhfl|jksh.comDas ist genau das Problem. Ich nutze eine Schablone. Diese soll in einer Tabelle die Freunde ausgeben(jede Reihe ein Freund.)
Wieviele Spalten hat diese Tabelle? So, wie Du es beschreibst, ist die Spaltenzahl undefiniert, weil abhängig von der maximalen Anzahl der E-Mail-Adressen. Oder stehen dann in der HTML-Tabelle alle E-Mail-Adressen in einer Zelle?
So wie es oben zurückgeliefert wird, bekomme man aber Probleme bei der Ausgabe. Wie soll ich so einen Freund beschreiben?
Das machst Du mit der Programmiersprache, die das HTML generiert.
Pseudocode:
Datensatzmenge = hole Datensatzmenge mit SELECT aus DB
Solange es Datensätze in der Datensatzmenge gibt:
FreundName:=aktDatensatz[Freunde.nachname]
FreundVorname:=aktDatensatz[Freunde.vorname]
AusgabeZeile:=FreundName+", "+FreundVorname
Solange aktDatensatz[Freunde.nachname]==FreundName
UND aktDatensatz[Freunde.vorname]==FreundVorname:
AusgabeZeile:=AusgabeZeile+", "+aktDatensatz[Kontaktdaten.email]
nächster Datensatz
Ende Solange
gebe aus: AusgabeZeile
nächster Datensatz
Ende Solange
viele Grüße
Axel
Ich verstehe es einfach nicht:
Hier sind meine beiden Tabellen:
CREATE TABLE contacts
(
id
int(11) NOT NULL auto_increment,
public
char(1) default NULL,
gender
char(1) NOT NULL default '',
title
varchar(5) NOT NULL default '',
name\_f
varchar(10) default NULL,
name\_l
varchar(20) NOT NULL default '0',
phone\_country
tinyint(4) NOT NULL default '0',
phone\_city
varchar(25) NOT NULL default '',
phone\_no
varchar(10) NOT NULL default '',
phone\_ext
varchar(5) NOT NULL default '',
fax\_city
varchar(25) NOT NULL default '',
fax\_no
varchar(10) NOT NULL default '',
fax\_ext
varchar(10) NOT NULL default '',
bio
text NOT NULL,
pic
varchar(25) NOT NULL default '',
PRIMARY KEY (id
),
UNIQUE KEY name
(name\_f
,name\_l
),
KEY id
(id
)
) TYPE=MyISAM AUTO_INCREMENT=29 ;
CREATE TABLE contacts\_functions
(
id
int(11) NOT NULL default '0',
id\_company
int(10) unsigned default NULL,
public
char(1) default NULL,
function
varchar(60) NOT NULL default '',
dienst
char(2) NOT NULL default '',
email
varchar(30) NOT NULL default '',
KEY id
(id
)
) TYPE=MyISAM;
CREATE TABLE contacts\_pictures
(
id\_contact
int(11) NOT NULL default '0',
picture
varchar(25) NOT NULL default '0',
width
smallint(6) NOT NULL default '0',
height
smallint(6) NOT NULL default '0',
ext
char(3) NOT NULL default ''
) TYPE=MyISAM;
Hier ist die SQL Anweisung:
$sql = "
SELECT c.id, c.pic, c.phone_country,
c.phone_city, c.phone_no, c.phone_ext, c.fax_city, c.fax_no, c.fax_ext, cf.function,
CONCAT(c.name_l, ', ', c.name_f) AS name,
LOWER(CONCAT(c.name_f, '_', c.name_l)) AS folder
FROM contacts c, lnk_company_contact lcc, contacts_functions cf
WHERE (c.id = lcc.id_contact)
AND (c.public = 'j')
AND (cf.id = c.id)
AND (lcc.id_company = '350')
ORDER BY c.name_l";
$page->assign('employees', $denclass->returnData($sql, $convert));
Hier ist die Ausgabe mit der Smarty Schablone:
{section name=i loop=$employees}
<div>
<img class="left" src="../images/person/{$employees[i].folder}/{$employees[i].folder}_round.gif" alt="{$employees[i].name}" />
<table>
<tr><td><a href="contact.php?id={$employees[i].id}">{$employees[i].name}</a></td></tr>
<tr><td><b>Funktion:</b> {$employees[i].function}</td></tr> <tr><td><b>Tel:</b> +{$employees[i].phone_country} {$employees[i].phone_city} {$employees[i].phone_no} {$employees[i].phone_ext}</td></tr> <tr><td><b>Fax:</b> +{$employees[i].phone_country} {$employees[i].fax_city} {$employees[i].fax_no} {$employees[i].fax_ext}</td></tr> </table>
<br style="clear: left;"/><br /> </div>
{/section}
Hallo,
{section name=i loop=$employees}
...
{/section}
Tja, mit Smarty kenne ich mich nicht aus. Aber, wenn das geht, musst Du den loop aufbrechen in einen äußeren für die geichbleibenden Felder (name und vorname im Beispiel) und einen inneren für die sich innerhalb diesre gleichbleibenden Felder verändernden Felder (email im Beispiel).
Eventuell steht ja in der Doku zu Smarty, ob und wie man in Smarty loops verschachteln kann.
viele Grüße
Axel
yo,
Kann man mit einem Select query alle Freunde ausgeben lassen UND auch zu jedem Freund gleichzeitig alle Email Adressen ? Oder benötigt man dazu 2 Queries ?
es geht mit einer, ABER dein datenbank-design ist nicht gerade "gut" gewählt. vielleicht solltest du erst mal ein wenig an dem feilen, bevor du dich an die abfragen machst.
Ilja
es geht mit einer, ABER dein datenbank-design ist nicht gerade "gut" gewählt. vielleicht solltest du erst mal ein wenig an dem feilen, bevor du dich an die abfragen machst.
Wie könnte man es denn verbessern ? Dache es wäre so optimal. Hatte vorher alles in einer Tabelle.
yo,
Wie könnte man es denn verbessern ? Dache es wäre so optimal. Hatte vorher alles in einer Tabelle.
manche besitzen hier fähigkeiten, indem sie ihre kristall-kugel befragen. mir ist diese fähigkeit leider nicht vergönnt, sprich ich müsste schon genauer wissen, wie dein ER modell aussieht.... ;-)
Ilja
Nun ja,
kannst du mir sagen wie ich Daten organisieren muss, so dass ich Freunde mehrere verschiedene Email Adressen zuteilen kann?
Und wie kann ich die Freunde dann bei der html Ausgabe untereinader listen, so dass aber von jedem alle Email Adressen angezeigt werden ?
Also die Namen sollen nur einmal vorkommen.
yo,
kannst du mir sagen wie ich Daten organisieren muss, so dass ich Freunde mehrere verschiedene Email Adressen zuteilen kann?
grundsätzlich zwei verschiendene vorgehensweisen. wenn du nur eine stark begrentzte anzahl von e-mail adressen pro user erlaubst, zum beispiel 2 oder 3 adressen, dann kannst du alles ruhig in eine tabelle übernehmen, sprich pro e-mail eine spalte. wenn nun aber die anzahl der e-mails pro person nicht reglementiert ist, dann musst du eine weitere tabelle bentuzen, 1:n.
Und wie kann ich die Freunde dann bei der html Ausgabe untereinader listen, so dass aber von jedem alle Email Adressen angezeigt werden ?
hängt ein wenig von dem datenmodell ab, ob eine oder zwei tabellen. bei nur einer tabelle ist das abfrage der e-mails pro peson trivial. bei zwei tabellen machst du einen outer left join und sortierst entsprechend der personen. dann hast du zwar bei jedem datensatz eine email adresse und die jeweilige person. aber die person nur einmal auszugeben kannst du beim auswerten der schleife leicht implementieren.
Ilja
hängt ein wenig von dem datenmodell ab, ob eine oder zwei tabellen. bei nur einer tabelle ist das abfrage der e-mails pro peson trivial. bei zwei tabellen machst du einen outer left join und sortierst entsprechend der personen. dann hast du zwar bei jedem datensatz eine email adresse und die jeweilige person. aber die person nur einmal auszugeben kannst du beim auswerten der schleife leicht implementieren.
Also es gibt 2 Tabellen. Aber on du es glaubst oder nicht, dass mit der Schleife fällt mir sehr schwer. Da bräuchte ich mal etwas Kode. Habe ein Brett vor dem Kopf.
yo,
Also es gibt 2 Tabellen. Aber on du es glaubst oder nicht, dass mit der Schleife fällt mir sehr schwer. Da bräuchte ich mal etwas Kode. Habe ein Brett vor dem Kopf.
ich wundere mich immer wieder, wie ein brett vor dem kopf überhaupt gehalten werden kann. ich hoffe, dass es nicht angenagelt ist....
wie auch immer, bei einem outer join kannst du zu jeden datensatz unter anderem die personen_id, namen und email-adresse anzeigen lassen und am besten nach der personen_id sortiert. die personen_id ist deshalb wichtig, weil namen durchaus gleich sein können. das wäre in etwa die abfrage.
um nun nur einmal den namen anzeigen zu lassen und nicht für jede e-mail einmal, machst du nun in der schleife einen vergleich, ob sich die personen_id geändert hat. dazu speicherst du die letzte personen_id in eine variable ab und vergleicht sie mit den neuen datensatz. ist sie gleich, dann handelt es sich auch um die gleiche person und du zeigst nur die zusätzliche e-mail an. ist sie ungleich dann kommt eine neue person.
Ilja
ich wundere mich immer wieder, wie ein brett vor dem kopf überhaupt gehalten werden kann. ich hoffe, dass es nicht angenagelt ist....
Ich auch!!!
wie auch immer, bei einem outer join kannst du zu jeden datensatz unter anderem die personen_id, namen und email-adresse anzeigen lassen und am besten nach der personen_id sortiert. die personen_id ist deshalb wichtig, weil namen durchaus gleich sein können. das wäre in etwa die abfrage.
Outer Joins benötige ich doch gar nicht. Es sind bereits alle Werte vergeben und zu jedem gibt ein entsprechende Zeile in der anderen Tabelle.
um nun nur einmal den namen anzeigen zu lassen und nicht für jede e-mail einmal, machst du nun in der schleife einen vergleich, ob sich die personen_id geändert hat. dazu speicherst du die letzte personen_id in eine variable ab und vergleicht sie mit den neuen datensatz. ist sie gleich, dann handelt es sich auch um die gleiche person und du zeigst nur die zusätzliche e-mail an. ist sie ungleich dann kommt eine neue person.
OK.
$sql = "SELECT c.id, c.pic, cf.email, cf.function,
CONCAT(c.phone_country, ' ', c.fax_city, ' ', c.fax_no, ' ', c.fax_ext) fax,
CONCAT(c.phone_country, ' ', c.phone_city, ' ', c.phone_no, ' ', c.phone_ext) phone,
CONCAT(c.name_l, ', ', c.name_f) AS name,
LOWER(CONCAT(c.name_f, '_', c.name_l)) AS folder
FROM contacts c, lnk_company_contact lcc, contacts_functions cf
WHERE (c.id = lcc.id_contact)
AND (c.public = 'j')
AND (cf.id = c.id)
AND (lcc.id_company = '350')
ORDER BY c.name_l";
$res =& $db->query($sql);
$anzahl = count($res);
$obergrenze = $anzahl - 1;
while ($row =& $res->fetchRow(DB_FETCHMODE_ASSOC)) {
$data[] = $row;
}
$richtig[] = $data[0];
$last_id = $richtig[0]['id'];
for ($i = 0; $i < $obergrenze; $i++) {
if ($last_id != $data[$i]['id']) { // different person
$last_id = $data[$i]['id'];
$richtig[] = $data[$i];
} else { // same person
$richtig[$i-1]['email'][] = $row[$i]['email'];
}
}
print "<pre>";
print_r($richtig);
print "</pre>";
}
Dieser Code gibt mir nur den ersten Mitarbeiter aus. Und nur mit einer Email Adresse. Wo liegt der Fehler ?
$sql = "SELECT c.id, c.pic, cf.email, cf.function,
CONCAT(c.phone_country, ' ', c.fax_city, ' ', c.fax_no, ' ', c.fax_ext) fax,
CONCAT(c.phone_country, ' ', c.phone_city, ' ', c.phone_no, ' ', c.phone_ext) phone,
CONCAT(c.name_l, ', ', c.name_f) AS name,
LOWER(CONCAT(c.name_f, '_', c.name_l)) AS folder
FROM contacts c, lnk_company_contact lcc, contacts_functions cf
WHERE (c.id = lcc.id_contact)
AND (c.public = 'j')
AND (cf.id = c.id)
AND (lcc.id_company = '350')
ORDER BY c.name_l";
Dieser Code gibt mir nur den ersten Mitarbeiter aus. Und nur mit einer Email Adresse. Wo liegt der Fehler ?
ziehe die verknüpfung mal aus WHERE raus und in ON (USING) rein.
richtig und lesbarer wäre:
SELECT spalten
FROM freunde f LEFT JOIN kontakte k USING(id)
WHERE bedingung
ORDER
$sql="SELECT function, c.id, cf.email,
CONCAT(c.phone_country, ' ', c.fax_city, ' ', c.fax_no, ' ', c.fax_ext) fax,
CONCAT(c.phone_country, ' ', c.phone_city, ' ', c.phone_no, ' ', c.phone_ext) phone,
LOWER(CONCAT(name_f, '_', name_l)) AS folder,
CONCAT(name_f, ' ', name_l) AS name
FROM contacts c, contacts_functions cf
WHERE (c.id = '".$id."') AND
(c.id = cf.id) AND
(cf.public = 'j')";
*/
$sql="SELECT function, id, email,
CONCAT(phone_country, ' ', fax_city, ' ', fax_no, ' ', fax_ext) AS fax,
CONCAT(phone_country, ' ', phone_city, ' ', phone_no, ' ', phone_ext) AS phone,
LOWER(CONCAT(name_f, '_', name_l)) AS folder,
CONCAT(name_f, ' ', name_l) AS name
FROM contacts JOIN contacts_functions
USING id
WHERE (public = 'j') AND (id = '".$id."')";
Warum gibt der untere QUERY einen Syntax Fehler ? Die beiden Queries sind meiner Meinung nach identisch. :(
Könnte es daran liegen, dass in beiden Tabellen die Spalte "public" vorkommt?
$sql="SELECT function, id, email,
CONCAT(phone_country, ' ', fax_city, ' ', fax_no, ' ', fax_ext) AS fax,
CONCAT(phone_country, ' ', phone_city, ' ', phone_no, ' ', phone_ext) AS phone,
LOWER(CONCAT(name_f, '_', name_l)) AS folder,
CONCAT(name_f, ' ', name_l) AS name
FROM contacts JOIN contacts_functions
USING id
WHERE (public = 'j') AND (id = '".$id."')";Warum gibt der untere QUERY einen Syntax Fehler ? Die beiden Queries sind meiner Meinung nach identisch. :(
id ist in beiden tabellen enthalten, sonst könnte man damit ja keinen join erstellen.
in der where bedingung nimmst du auf id bezug. eigentlich sollte der ja dann aus beiden tabellen gleich sein, und somit wäre es egal aus welcher tabelle verglichen wird.
die sql interpreter sind aber formal aufgebaut. daher wird dieser sonderfall nicht erkannt, und der interpreter will wissen, welche spalte nun gemeint ist, da id nicht eindeutig ist.
also: tabelle.id schreiben.
So sieht es fast schon mal ungefähr so aus, wie es sein soll.
while ($row =& $res->fetchRow(DB_FETCHMODE_ASSOC)) {
$data[] = $row;
}
$richtig[] = $data[0];
$last_id = $richtig[0]['id'];
for ($i = 0; $i < $obergrenze; $i++) {
if ($last_id != $data[$i]['id']) { // different person
$last_id = $data[$i]['id'];
$richtig[] = $data[$i];
} else { // same person
$richtig[count($richtig)-1]['email'] = $data[count($richtig)]['email'].", ".$data[count($richtig)]['email'];
}
}
print "<pre>";
print_r($richtig);
print "</pre>";
ergibt:
Array
(
[0] => Array
(
[id] => 1
[pic] => ...
[email] => email1@..., email2@...
[function] => Vertriebsinnendienst Nord & Ost
[fax] => ...
[phone] => ...
[name] => Nachname1, Vorname1
[folder] => ...
)
[1] => Array
(
[id] => 24
[pic] => ...
[email] => email1@...
[function] => Export Frankreich, Belgien, Niederlande
[fax] => ...
[phone] => ...
[name] => Nachname2, Vorname2
[folder] => ...
)
Es soll aber so aussehen:
Array
(
[0] => Array
(
[id] => 1
[pic] => ...
[email] =>
[0] => Array
(
[0] => email1@...,
[1] => email2@...,
...
)
[function] => Vertriebsinnendienst Nord & Ost
[fax] => ...
[phone] => ...
[name] => Nachname1, Vorname1
[folder] => ...
)
es geht mit einer, ABER dein datenbank-design ist nicht gerade "gut" gewählt. vielleicht solltest du erst mal ein wenig an dem feilen, bevor du dich an die abfragen machst.
Wie könnte man es denn verbessern ? Dache es wäre so optimal. Hatte vorher alles in einer Tabelle.
das 'design' ist schon gut so:
du hast eine 1:n beziehung von person und kontakt. das ist ok.
nur weil die ausprägungen manchmal doppelt sein können, muß hier nicht unbedingt weiter normalisiert werden.
die ausprägungen des kontaktes können ja diverse qualitäten haben:
büro, zuhause, auf dem klo oder auch im himmel.
das gleiche gilt fürs telefon (nicht jeder hat ja ein teuren handy-vertrag).
ich benutze auch verschiedene emails für diverse kontakte.
also ist die schnittmenge nicht unbedingt ein kriterium für weitere normalisierung, nur weil es manchmal redundanzen gibt.
aber wenn du lust hast, kannst du ja noch die tabellen email, telefon und ort erstellen. diese benötigen aber auch referenzen, welche ihrerseits natürlich auch wieder platz fressen. bei der abfrage kosten diese dann auch widerum zusätzliche kraft, welcher den server extra belastet.
also überlegs dir nochmal, die normalisierung ins extrem (praxisfremd) zu treiben.