Archiv verlassen und diese Seite im Standarddesign anzeigen : Mittels Erdberechnung + Ort Angebot wählen
Hallo,
ich habe ein kleines Problem bei meiner SQL Abfrage zuerst erstmal die Abfrage
SELECT ort, plz,(".$earthRadius."*SQRT(2*(1-cos(RADIANS(kob))*cos(".$breite.")*(sin(RADIANS(kol))*
sin(".$laenge.")+cos(RADIANS(kol))*cos(".$laenge."))-sin(RADIANS(kob))*sin(".$breite.")))) AS Distance
FROM karte
WHERE ".$earthRadius."*
SQRT(2*(1-cos(RADIANS(kob))*cos(".$breite.")*(sin(RADIANS(kol))*sin(".$laenge.")+cos(RADIANS(kol))*
cos(".$laenge."))-sin(RADIANS(kob))*sin(".$breite."))) <= ".$umkreis."
AND
(SELECT
lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID,
lsn_arts.festpreis, lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae
FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts, lsn_kat lsn_kat
where
lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online = 1
AND lsn_kat.SHOP = 'L'
)
AND
ORDER BY Distance
Leider bekomme ich immer den Fehler
#1241 - Operand should contain 1 column(s)
Leider finde ich den Fehler nicht, kann eigentlich (hoffentlich) nichts gravierendes sein.
Bis zur Where soll er nur die Distancen ausrechnen (Mittels der Erdkrümmung und Geo Koor.)
In der zweiten Select soll er dann das passende Angebot rausfiltern.
Beide Select ansich funktionieren, zusammen leider nicht.
Kann vielleicht jemand mal drüber gucken? Und mir einen Tipp geben?
Vielen Dank
PHP-Desaster 29-09-2007, 13:07 WHERE ...
AND
(SELECT ...)
AND
ORDER BY DistanceIst doch irgendwie Käse, oder meinst du nicht??
stimmt du hast recht, das AND sollte nicht sein, aber die Select müsste eigentlich funktionieren...
Es müsste doch gehn, dass ich eine weitere SELECT in die WHERE baue oder nicht ?
Der obere Teile bestimmt die Orte mit den Distanzen und leider bekomme ich unsere Angebote dort nicht hineine.
Normalerweise müsste ich dann vergleichen ... ORT mit ORT ..
aber es wird doch wahrscheinlich auch nicht funktionieren wenn ich es so mache
ort = (SELECT
lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID,
lsn_arts.festpreis, lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae
FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts, lsn_kat lsn_kat
where
lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online = 1
AND lsn_kat.SHOP = 'L'
)
Oder geht das garnicht?
ghostgambler 29-09-2007, 20:07 Ich persönlich verstehe nicht mal was du da raus haben willst durch den Query...
Ich gebe zu es ist auch nicht leicht.
ich habe eine Tabelle mit folgenden Daten
Kol = Längengrad
Kob = Breitengrad
plz = Postleitzahl
ort = die Orte
Diese Tabelle heisst Karte
Der Teil Berechnet die richtigen Koortdinaten von einer anderen Tabelle:
SELECT ort, plz,(6367.41*SQRT(2*(1-cos(RADIANS(kob))*cos(0.89461822247829)*(sin(RADIANS(kol))* sin(0.12474027120029)+cos(RADIANS(kol))*cos(0.12474027120029))-sin(RADIANS(kob))*sin(0.89461822247829)))) AS Distance
FROM karte
WHERE 6367.41* SQRT(2*(1-cos(RADIANS(kob))*cos(0.89461822247829)*(sin(RADIANS(kol))*sin(0.12474027120029)+cos(RADIANS(kol))* cos(0.12474027120029))-sin(RADIANS(kob))*sin(0.89461822247829))) <= 50 ORDER BY Distance
Die Ausgabe sieht folgendermaßen aus bei dieser Abfrage
ort plz Distance
Düsseldorf 40212 0.6805006935835
Düsseldorf 40211 0.78988133690809
Düsseldorf 40215 0.8733307983443
Düsseldorf 40213 1.3089818727118
Düsseldorf 40227 1.3104736434284
Düsseldorf 40233 1.4096546047075
Düsseldorf 40217 1.5048117182945
usw.
bisher sieht es so aus, dass ich die ausgegebenen Orte in einen Array speichere
und dann folgende Abfrage benutze
SELECT
lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID,
lsn_arts.festpreis, lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae
FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts, lsn_kat lsn_kat
where
(";
$globaler_ort = array_unique($globaler_ort);
foreach($globaler_ort as $ort){
$sql_angebote .= "lsn_ang.ort = '".$ort."' or "; }
$sql_angebote = substr($sql_angebote,0,strlen($sql_angebote)-3);
$sql_angebote .= ")
AND lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online = 1
AND lsn_kat.SHOP = 'L'
GROUP BY lsn_ang.ort
Nur ehrlich ... das ist scheisse lahm 3 -5 Sekunde und das geht nicht.
Ich denke das man das mit SQL direkt und schneller machen kann, deshalb dachte ich das die obere Abfrage funktionieren könnte, dann könnte ich direkt die Angebote den Orten zuweisen.
ghostgambler 29-09-2007, 20:42 Warum machst du nicht einfach einen JOIN?
Alternativ ein SUBSELECT mit
SELECT * FROM lsn_ang WHERE
lsn_ang.ort IN (<dein 1. select>)
weil es wahrscheinlich nicht geht, du musst dir vorstellen die Ausgebe sind ca. 10 orte ...
Aber vielleicht funktioniert es ja, ich teste es und melde mich dann...
Also ich habe es geteste, die Idee ist echt gut, hätte mir dadurch viel arbeit ersparrt ...
Leider bekomme ich folgende Fehlermeldung bei der Abfrage
SELECT * FROM lsn_ang
WHERE lsn_ang.ort
IN
( SELECT ort, plz,(6367.41*SQRT(2*(1-cos(RADIANS(kob))*
cos(0.89461822247829)*(sin(RADIANS(kol))* sin(0.12474027120029)+cos(RADIANS(kol))*
cos(0.12474027120029))-sin(RADIANS(kob))*
sin(0.89461822247829)))) AS Distance FROM karte WHERE 6367.41* SQRT(2*(1-cos(RADIANS(kob))*cos(0.89461822247829)*
(sin(RADIANS(kol))*
sin(0.12474027120029)+cos(RADIANS(kol))* cos(0.12474027120029))-sin(RADIANS(kob))*
sin(0.89461822247829))) <= 50 ORDER BY Distance )
#1241 - Operand should contain 1 column(s)
Also irgend eine Spalte findet der nicht.
ghostgambler 29-09-2007, 21:11 Meine Güte, was ist so schwer daran das Problem in Teilprobleme zu zerlegen?
Kürze den Query bis er geht und bau dann schrittweise auf um zu gucken was genau den Fehler verursacht.
[edit]
Der Fehler ist, dass du 3 Spalten im SUBSELECT angibst - wo soll der denn bitte da gucken?! Du musst genau EINE Spalte angeben!!!
Danke für den Tip!
Ich weiss wo das prob ist, aber ich brauche die Daten aus der Select (ich brauch sowohl plz, als auch den Ort und die Distanze)
Deshalb kann ich nichts weg kürzen.
kann ich in der in Select vielleicht mehrere sachen vergleichen
in select lsn_ang.ort, lsn_ang.plz, karte.plz, karte.ort oder so ähnlich, weil die zweite Select muss so bleiben damit sie funktioniert
tontechniker 29-09-2007, 22:57 Ich weiss wo das prob ist, aber ich brauche die Daten aus der Select (ich brauch sowohl plz, als auch den Ort und die Distanze) Wäre doch sinnvoller die in diesem Fall extra abzufragen oder? Ach und Code umbrechen bitte.
Hatte ich vorher und dann hab ich sie im array gespeichert und dann in der SQL abfrage mittels foreach ausgegeben
ELECT
lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID,
lsn_arts.festpreis, lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae
FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts,
lsn_kat lsn_kat
where
(";
$globaler_ort = array_unique($globaler_ort);
foreach($globaler_ort as $ort){
$sql_angebote .= "lsn_ang.ort = '".$ort."' or "; }
$sql_angebote = substr($sql_angebote,0,strlen($sql_angebote)-3);
$sql_angebote .= ")
AND lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online = 1
AND lsn_kat.SHOP = 'L'
GROUP BY lsn_ang.ort
ghostgambler 30-09-2007, 07:59 Warum nicht einfach einen JOIN?
Das ist nicht nur einfacher sondern geht auch schneller...
SELECT
lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID,
lsn_arts.festpreis, lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae,
(".$earthRadius."*SQRT(2*(1-cos(RADIANS(kob))*cos(".$breite.")*(sin(RADIANS(kol))*
sin(".$laenge.")+cos(RADIANS(kol))*cos(".$laenge."))-sin(RADIANS(kob))*sin(".$breite.")))) AS Distance
FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts, lsn_kat lsn_kat
INNER JOIN karte karte ON lsn_kat.ort = karte.ort
where
lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online = 1
AND lsn_kat.SHOP = 'L'
ORDER BY Distance
Auf den Ansatz hätte ich auch kommen können, danke erstmal dafür
musste allerdings Änderungen vornehmen, da es leider einen Fehler verursachte bei der InnerJoin
#1066 - Not unique table/alias: 'karte'
Also habe ich die Innerjoin raus gelassen und es funktioniert... l
SELECT lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz,
karte.kol, karte.kob, lsn_arts.ID, lsn_arts.festpreis,
lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae,
( 6367.41 * SQRT( 2 * ( 1 - cos( RADIANS( kob ) )
* cos( 0.89461822247829 ) * ( sin( RADIANS( kol ) ) * sin( 0.12474027120029 ) + cos( RADIANS( kol ) ) *
cos( 0.12474027120029 ) ) - sin( RADIANS( kob ) ) *
sin( 0.89461822247829 ) ) ) ) AS Distance
FROM lsn_ang lsn_ang, karte karte, lsn_arts
lsn_arts, lsn_kat lsn_kat
WHERE lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online =1
AND lsn_kat.SHOP = 'L'
ORDER BY Distance
Leider ist die Performance sehr sehr schlecht
PHPmyAdmin meldet
Zeige Datensätze 0 - 29 (2.079 insgesamt, die Abfrage dauerte 61.6757 sek.)
Und das geht echt nicht, jetzt habe ich erfolglos versucht die zweite Berechnung mit einzubeziehen
WHERE ".$earthRadius."*SQRT(2*(1-cos(RADIANS(kob))*cos(".$breite.")*(sin(RADIANS(kol))*
sin(".$laenge.")+cos(RADIANS(kol))* cos(".$laenge."))-sin(RADIANS(kob))*sin(".$breite."))) <= ".$umkreis."
Leider ist mir das auch nicht gelungen, woran kann es liegen das es so lannnge dauert ?
[edit]
Ich habe es ans laufen bekommen mit folgendem CODE
SELECT lsn_ang.ort, lsn_ang.plz, karte.ort, karte.plz, karte.kol, karte.kob, lsn_arts.ID, lsn_arts.festpreis,
lsn_arts.maske, lsn_arts.zukat, lsn_arts.art_kurz,
lsn_arts.art_long, lsn_kat.ID, lsn_ang.preis_angebot, lsn_ang.preis_normal, lsn_kat.long, lsn_kat.tae,
( 6367.41 * SQRT( 2 * ( 1 - cos( RADIANS( kob ) )
* cos( 0.89461822247829 ) * ( sin( RADIANS( kol ) ) * sin( 0.12474027120029 ) + cos( RADIANS( kol ) ) * cos( 0.12474027120029 ) ) - sin( RADIANS( kob ) ) * sin( 0.89461822247829 ) ) ) ) AS Distance
FROM lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts,
lsn_kat lsn_kat
WHERE lsn_ang.plz = karte.plz
AND lsn_kat.ID = lsn_arts.zukat
AND lsn_ang.zuart = lsn_arts.ID
AND lsn_ang.online =1
AND lsn_kat.SHOP = 'L'
AND 6367.41 * SQRT( 2 * ( 1 - cos( RADIANS( kob ) )
* cos( 0.89461822247829 ) * ( sin( RADIANS( kol ) )
* sin( 0.12474027120029 ) + cos( RADIANS( kol ) )
* cos( 0.12474027120029 ) ) - sin( RADIANS( kob ) )
* sin( 0.89461822247829 ) ) ) <=50
ORDER BY Distance
Nur dauert es immernoch
Zeige Datensätze 0 - 116 (117 insgesamt, die Abfrage dauerte 1.3569 sek.)
Oder ist das in Ordnung? Oder kann man noch optimieren?
tontechniker 30-09-2007, 11:19 #1066 - Not unique table/alias: 'karte' Du kannst natürlich nicht zweimal karte benutzen, erstere muss raus: FROM
lsn_ang lsn_ang, karte karte, lsn_arts lsn_arts, lsn_kat lsn_kat
INNER JOIN karte karte ON lsn_kat.ort = karte.ort
where Leider ist die Performance sehr sehr schlecht Hast du auch schonmal ausprobiert warum, einzelne Query teile rausgenommen?
ghostgambler 30-09-2007, 11:26 EXPLAIN <query>
und Ausgabe posten~
id | select_type | table | type | possible_key |key | key_len | ref | rows | Extra
------------------------------------------------------------------------------------
1 | SIMPLE |lsn_ang | ALL | NULL |NULL| NULL |NULL | 7128 |Using where; Using temporary; Using filesort
1 | SIMPLE | karte | ALL| NULL | NULL| NULL | NULL 8178 Using where
1 SIMPLE lsn_arts eq_ref PRIMARY PRIMARY 4 db83250_11.lsn_ang.zuart 1
1 SIMPLE lsn_kat eq_ref PRIMARY PRIMARY 4 db83250_11.lsn_arts.zukat 1 Using where
Ich hoffe das kann man so erkennen.
EXPLAIN kannte ich noch garnicht
8178 rows is schon extrem hart.
ghostgambler 30-09-2007, 13:08 karte.plz würde sich über einen Index freuen.
okay, ich kann karte.plz noch mit lsn_ang.plz vergleichen, aber die Performance ist dann noch schlechter, sie liegt dann bei < 3 sek.
tontechniker 30-09-2007, 15:42 okay, ich kann karte.plz noch mit lsn_ang.plz vergleichen, aber die Performance ist dann noch schlechter, sie liegt dann bei < 3 sek. Du hast jetzt schon in der Datenbank einen Index angelegt?
okay habe den Index für die Tabelle Karte definiert.
Leute ihr seit einfach die Genialsten.
Ich danke euch .. durch das indexieren der Spalten ist es von 36 sekunden auf 0.34 sekunden gefallen.
Ich danke euch !!!!!
Also eine kleine Frage habe ich allerdings noch... (leider)
Ich habe die Ausgabe die ich brauche..
Sieht so ungefähr aus
Ort PLZ ort PLZ Kol Kob etc ..
Jetzt habe ich aber angenommen 10 Angebote im Raum Düsseldorf..
Die Angebote möchte ich alle anzeigen lassen, aber nur einmal den Ort .
Ich dachte an GROUP By lsn_ang.ort ORDER BY Distance, lsn_ang.ort
nur das geht leider nicht, der Groupiert zwar die Orte aber er laesst die Angebote nicht bestehen, sondern nimmt die raus, kann ich das irgendwie so machen, das er die Orte Groupiert aber die Angebote bestehen lässt?
So das ich die Ausgabe so machen könnte
ORT = DÜSSELDORF
Aktivität = Ballon etc
Geht das? Oder muss ich das mit PHP Realisieren, wäre eine enorme Speed Bremse
ghostgambler 30-09-2007, 18:47 Ähm... nein? Das macht man immer mit PHP und bremst eigentlich gar nicht großartig?! Oo
Wobei das vielleicht mit GROUP_CONCAT lösbar wäre - je nachdem was du machen willst.
|
|