Subquery
Ik krijg nu de melding #1241 - Operand should contain 1 column(s)
Weet iemand hoe ik alleen de zip_code krijg zonder de distance kolom in de subquery?
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
$query = "SELECT * FROM venue,events WHERE venue.postcode IN
(SELECT zip_code, ( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) ) ) AS distance FROM demo HAVING distance < '{$_POST['range']}' ORDER BY distance)
AND events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}' AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
ORDER BY events.startdatum ASC";
?>
$query = "SELECT * FROM venue,events WHERE venue.postcode IN
(SELECT zip_code, ( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) ) ) AS distance FROM demo HAVING distance < '{$_POST['range']}' ORDER BY distance)
AND events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}' AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
ORDER BY events.startdatum ASC";
?>
ik heb nu twee queries gemaakt die ik apart uitvoer wat werkt maar het lijkt me dat dit toch ook te doen moet zijn met 1 query?
De formule zorgt ervoor dat de postcodes in een opgegeven range worden opgehaald.De distance kolom wordt dus wel gebruikt maar wil ik niet in mijn WHERE IN hebben.
Iemand?
Gewijzigd op 07/06/2012 11:10:19 door N K
hoe ziet je query er nu uit ? ( dus met 2 aparte ) en ik weet niet of dit nou wel zo een goed idee is om met subquery te werken. is het niet handiger dit met joins te doen?
Dus
SELECT zip_code
FROM demo
WHERE "distance berekening" < "getal"
De order by heb je hier toch niet nodig.
Ik ga dit vanavond eens proberen
Thanx!
Jouw code is dus onveilig, zo lek als een mandje... Google er eens op, dit is bekend sinds eind jaren '90.
Dit was even snel een opzetje of de query zou werken. Ik zal voortaan bij een vraag dit meteen in de code zetten want als ik het niet doe wordt ik er toch telkens op gewezen. (wat uiteraard helemaal goed is ;)
Toevoeging op 07/06/2012 18:21:27:
Oke hij werkt ( stuk sneller zonder api)!
Ik heb nu dit (nog zonder beveiliging):
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$query = "SELECT * FROM venue,events WHERE venue.postcode IN (
SELECT zip_code from demo where ( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) ) ) < ('{$_POST['range']}'))
AND events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}'
AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
ORDER BY events.startdatum
ASC";
?>
$query = "SELECT * FROM venue,events WHERE venue.postcode IN (
SELECT zip_code from demo where ( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) ) ) < ('{$_POST['range']}'))
AND events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}'
AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
ORDER BY events.startdatum
ASC";
?>
Ik wil toch uiteindelijk sorteren op distance(calculatie) van laag naar hoog. Kan ik die calculatie toch nog ergens benoemen zodat ik hier op kan sorteren?
iemand?
Stel, je hebt iets als
Je kan dat omvormen to dit:
Code (php)
1
2
3
2
3
SELECT name, distance, (distance < 50) AS distace_okay
FROM my_table
HAVING distace_okay = 1
FROM my_table
HAVING distace_okay = 1
Dat maakt dat je distace_okay kan gebruiken om te sorteren ( ORDER BY distace_okay)
-----
Je moet dus iets construeren in deze trend (geen garantie dat dit werkt als je het klakkeloos copy/paste)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT zip_code, (
( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) )
)
-
('{$_POST['range']}')
) AS distance_dif
FROM demo
WHERE
events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}' AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
HAVING distance_dif <= 0
ORDER BY distance_dif
( 3959 * acos( cos( radians('{$_POST['latitude']}') ) * cos( radians( lat ) )
* cos( radians( lon ) - radians('{$_POST['longitude']}') ) + sin( radians('{$_POST['latitude']}') )
* sin( radians( lat ) ) )
)
-
('{$_POST['range']}')
) AS distance_dif
FROM demo
WHERE
events.categorie IN ('{$_POST['Muziek']}','{$_POST['Musea']}','{$_POST['Beurzen']}','{$_POST['Theater']}','{$_POST['Uitgaan']}')
AND events.startdatum >= '{$_POST['start']}' AND (events.venue_id = venue.venue_id)
AND (venue.venue_id = events.venue_id)
HAVING distance_dif <= 0
ORDER BY distance_dif
(Probeer misschien eerst zonder HAVING distance_dif <= 0)
Gewijzigd op 11/06/2012 17:26:39 door Kris Peeters
Even een voorbeeld(ingekort)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
SELECT v.vname, v.startdatum, pc.distance
FROM
(SELECT venue.name FROM venue
JOIN events USING venue_id
WHERE events.categorie IN [list]
AND events.startdatum >= [de datum]) AS v
JOIN
(SELECT zipcode, [berekening] AS distance
FROM demo
WHERE [berekening] = [vergelijking]) AS pc
ON pc.zipcode = v.zipcode
ORDER BY pc.distance
FROM
(SELECT venue.name FROM venue
JOIN events USING venue_id
WHERE events.categorie IN [list]
AND events.startdatum >= [de datum]) AS v
JOIN
(SELECT zipcode, [berekening] AS distance
FROM demo
WHERE [berekening] = [vergelijking]) AS pc
ON pc.zipcode = v.zipcode
ORDER BY pc.distance
Een join werkt over het algemeen stukken sneller dan een subquery achter een IN.
@Kris
HAVING is een GROUP BY clause
Gewijzigd op 11/06/2012 18:10:47 door Ger van Steenderen
Dank, ik ga het eens proberen!
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
SELECT v.name,
e.startdatum,
GetDistance(@org_lat, @org_long, pc.lat, pc.long) AS dist
FROM venue AS v
JOIN events AS e USING venue_id
JOIN demo AS pc ON v.zipcode = pc.zipcode
WHERE
GetDistance(@org_lat, @org_long, pc.lat, pc.long) <= @range
AND
e.categorie IN [list]
AND
e.startdatum => DATE(NOW())
ORDER BY dist
e.startdatum,
GetDistance(@org_lat, @org_long, pc.lat, pc.long) AS dist
FROM venue AS v
JOIN events AS e USING venue_id
JOIN demo AS pc ON v.zipcode = pc.zipcode
WHERE
GetDistance(@org_lat, @org_long, pc.lat, pc.long) <= @range
AND
e.categorie IN [list]
AND
e.startdatum => DATE(NOW())
ORDER BY dist
Dan een een functie maken voor de afstandsberekening:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
DELIMITER $$
CREATE FUNCTION GetDistance(orgLat float, orgLong float, destLat float, destLong float) RETURNS int(11)
BEGIN
DECLARE dist INT(11);
SET dist := ROUND(6371 *
acos(cos(radians(orgLat) ) *
cos(radians(destLat)) *
cos(radians(destLong) - radians(orgLong)) + sin(radians(orgLat))
* sin(radians(destLat))));
RETURN dist;
END
DELIMITER ;
CREATE FUNCTION GetDistance(orgLat float, orgLong float, destLat float, destLong float) RETURNS int(11)
BEGIN
DECLARE dist INT(11);
SET dist := ROUND(6371 *
acos(cos(radians(orgLat) ) *
cos(radians(destLat)) *
cos(radians(destLong) - radians(orgLong)) + sin(radians(orgLat))
* sin(radians(destLat))));
RETURN dist;
END
DELIMITER ;
Kan je hem wat makkelijker hergebruiken.
Overigens had je de straal van de aarde in mijlen staan.
Zie je het verschil(buiten de functie)?
Toevoeging op 12/06/2012 09:26:09:
PS. Je moet natuurlijk de uservars vervangen door jouw POST vars
Gewijzigd op 12/06/2012 09:28:49 door Ger van Steenderen
Super, bedankt, dit had ik zelf niet kunnen bedenken.
Ik ga er vanavond eens voor zitten. Ben nog een beginner.;)
p.s. Van de straal van de aarde had ik het opgemerkt. Deze had ik intussen aangepast.
Toch bedankt.
N K op 12/06/2012 15:33:27:
@Ger
.... Ben nog een beginner.;)
.....
.... Ben nog een beginner.;)
.....
Geen punt ;-)
Om het verschil uit te leggen:
In de eerste query worden uit de postcode tabel een hele rits postcodes geselecteerd die aan de afstandss voorwaarden voldoen en daarna wordt er gejoined op de postcode van het event.
In de laatse query worden de lengte- en breedte graad uit de postcode tabel direct gekoppeld aan de postcode uit de venue tabel, en dan bepaald of er aan de afstands voorwaarde voldaan wordt.
Dat maakt de query aanzienlijk sneller.
Onderstaand wat ik nu heb:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
$query1= "DELIMITER $$
CREATE FUNCTION GetDistance(orgLat float, orgLong float, destLat float, destLong float) RETURNS int(11)
BEGIN
DECLARE dist INT(11);
SET dist := ROUND(6371 *
acos(cos(radians(orgLat) ) *
cos(radians(destLat)) *
cos(radians(destLong) - radians(orgLong)) + sin(radians(orgLat))
* sin(radians(destLat))));
RETURN dist;
END
DELIMITER" ;
$query2="SELECT v.name,
e.startdate,
GetDistance(('{$_POST['latitude']}'), ('{$_POST['longitude']}'), zc.lat, zc.long) AS dist
FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.4pp = zc.4pp
WHERE
GetDistance(('{$_POST['latitude']}'), ('{$_POST['longitude']}'), zc.lat, zc.long) <= ('{$_POST['range']}')
AND
e.categorie IN ('{$_POST['concerten']}','{$_POST['tentoonstellingen']}','{$_POST['theater']}','{$_POST['markten']}')
AND
e.startdate => >= '{$_POST['start']}')
ORDER BY dist";
?>
$query1= "DELIMITER $$
CREATE FUNCTION GetDistance(orgLat float, orgLong float, destLat float, destLong float) RETURNS int(11)
BEGIN
DECLARE dist INT(11);
SET dist := ROUND(6371 *
acos(cos(radians(orgLat) ) *
cos(radians(destLat)) *
cos(radians(destLong) - radians(orgLong)) + sin(radians(orgLat))
* sin(radians(destLat))));
RETURN dist;
END
DELIMITER" ;
$query2="SELECT v.name,
e.startdate,
GetDistance(('{$_POST['latitude']}'), ('{$_POST['longitude']}'), zc.lat, zc.long) AS dist
FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.4pp = zc.4pp
WHERE
GetDistance(('{$_POST['latitude']}'), ('{$_POST['longitude']}'), zc.lat, zc.long) <= ('{$_POST['range']}')
AND
e.categorie IN ('{$_POST['concerten']}','{$_POST['tentoonstellingen']}','{$_POST['theater']}','{$_POST['markten']}')
AND
e.startdate => >= '{$_POST['start']}')
ORDER BY dist";
?>
Ik begrijp niet helemaal hoe ik die functie moet integreren in het geheel..Moet ik die nu van tevoren uitvoeren?
Daaarna kun je hem gewoon net zoals de standaard mysql funties aanroepen in een query.
Ik krijg nu een syntax error maar zie de fout maar niet..:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'venue_id JOIN zipcode AS zc ON v.4pp = zc.4pp WHERE GetDistance(('51.84961755997' at line 1
Code (php)
1
SELECT v.name, e.startdate, GetDistance(('51.849617559975805'), ('5.813988671874995'), zc.lat, zc.lon) AS dist FROM venue AS v JOIN event AS e USING venue_id JOIN zipcode AS zc ON v.4pp = zc.4pp WHERE GetDistance(('51.849617559975805'), ('5.813988671874995'), zc.lat, zc.long) <= ('30') AND e.categorie IN ('concerten','tentoonstellingen','theater','markten') AND e.startdate => >= '2012-06-01') ORDER BY dist
Is het wel gelukt om de funcie aan te maken?
Ik heb de functie in phpmyadmin uitgevoerd en dat leverde geen fouten op.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
SELECT v.name, e.startdate,
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) AS dist FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.4pp = zc.4pp
WHERE
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.long) <= 30
AND
e.categorie IN ('concerten','tentoonstellingen','theater','markten')
AND
e.startdate => '2012-06-01'
ORDER BY dist
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) AS dist FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.4pp = zc.4pp
WHERE
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.long) <= 30
AND
e.categorie IN ('concerten','tentoonstellingen','theater','markten')
AND
e.startdate => '2012-06-01'
ORDER BY dist
Al die haakjes zijn niet nodig, decimale getallen zijn geen strings, en je had staan:
e.startdate => => '2012-06-01'
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'venue_id JOIN zipcode AS zc ON v.zipcode = zc.zipcode WHERE GetDistance(5' at line 3
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
SELECT v.name, e.startdate,
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) AS dist FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.zipcode = zc.zipcode
WHERE
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) <= 30
AND
e.categorie IN ('concerten','tentoonstellingen','theater','markten')
AND
e.startdate => '2012-06-01'
ORDER BY dist
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) AS dist FROM venue AS v
JOIN event AS e USING venue_id
JOIN zipcode AS zc ON v.zipcode = zc.zipcode
WHERE
GetDistance(51.849617559975805, 5.813988671874995, zc.lat, zc.lon) <= 30
AND
e.categorie IN ('concerten','tentoonstellingen','theater','markten')
AND
e.startdate => '2012-06-01'
ORDER BY dist