Warnung: file_put_contents(/home/www/web1/html/php_dev/test.txt) [function.file-put-contents]: failed to open stream: Permission denied in /home/www/web1/html/php_dev/sys/lib.activity.php (Zeile 58)
Mittels Erdberechnung + Ort Angebot wählen [Archiv] - PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr

- Ad -
php-resource




Archiv verlassen und diese Seite im Standarddesign anzeigen :
Mittels Erdberechnung + Ort Angebot wählen


 
none
29-09-2007, 12:41 
 
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??

 
none
29-09-2007, 19:46 
 
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...

 
none
29-09-2007, 20:33 
 
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>)

 
none
29-09-2007, 20:45 
 
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!!!

 
none
29-09-2007, 22:13 
 
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.

 
none
29-09-2007, 23:09 
 
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

 
none
30-09-2007, 11:11 
 
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~

 
none
30-09-2007, 11:39 
 
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.

 
none
30-09-2007, 15:08 
 
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?

 
none
30-09-2007, 16:03 
 
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 !!!!!

 
none
30-09-2007, 18:30 
 
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.


Alle Zeitangaben in WEZ +2. Es ist jetzt 23:02 Uhr.