Reputation: 2466
I store availability for all registered user by three columns in a comma separated strings like below:
user 1:
teaching: english
morning = '';
afternoon = 'Thrs,Fri,Sat,Sun';
evening = 'Thrs,Fri,Sat,Sun';
User 2
teaching: english
morning = 'Sat';
afternoon = 'Sat,Sun,Fri';
evening = 'Sat,Sun,Fri';
Say I search for tutor who're available afternoon and evening Saturdays. I thought query would return both of them as both user's afternoon and evening columns has 'Sat'. But it returns empty array.
This is my browser interpreted query. I ran this in phpmyadmin but doesn't return any result.
SELECT * , (3956 * 2 * ASIN(SQRT( POWER(SIN(('2.993518' - lat) * pi()/180 / 2), 2) +COS('2.993518' * pi()/180) * COS(lat * pi()/180) * POWER(SIN(('101.7874058' - lon) * pi()/180 / 2), 2) ))) as distance from posts WHERE posts.subname LIKE '%english%' AND posts.pricing <= '115'
AND (posts.afternoon IN ('Sat') OR posts.evening IN ('Sat')) GROUP BY posts.UUID having distance <= '40' order by distance
The same way here I'm trying to seek users available on afternoon and evening 'Thursdays'. I suppose it should return user1 because only user1 one available on Thursdays but it doesn't return any result:
SELECT * , (3956 * 2 * ASIN(SQRT( POWER(SIN(('2.993518' - lat) * pi()/180 / 2), 2) +COS('2.993518' * pi()/180) * COS(lat * pi()/180) * POWER(SIN(('101.7874058' - lon) * pi()/180 / 2), 2) ))) as distance from posts WHERE posts.subname LIKE '%flute%' AND posts.pricing <= '115'
AND (posts.afternoon IN ('Thrs') OR posts.evening IN ('Thrs')) GROUP BY posts.UUID having distance <= '40' order by distance
So when on earth it returns result ?
When I search for Saturday for morning,afternoon and evening. I just don't understand how this query perform the search.Why I'm not getting expected results, where's my mistake? It would be helpful if anyone help me with this because I've wasted many days on this!
FULL PHP code for the above:
<?php
JSON formatted data received via ajax
$return = '{"avail":["Wed-2,Thrs-2","Thrs-3"]}';
In the above -1 means for monrning, -2 for afternoon and -3 for evening.I'm categorising them below.'
$avail = $data['avail'];
$days = array();
$cols = array();
$size = sizeof($avail);
if(($avail != "")&&($size > 1)){
$periods = array();
foreach($avail as $v){
list($day, $column) = explode("-", $v); // make sure you validated the data to avoid errors
$periods[$column][] = "'" . mysql_escape_string($day) . "'"; //strtolower// PHP would automatically create an empty array if $periods[$column] was not defined
}
$intToCol = array(1 => "morning", 2 => "afternoon", 3 => "evening");
// $periods should now be identical to ["2" => ["'sun'", "'mon'"], "3" => ["'sun'"]]
$conditions = array();
foreach($periods as $int => $days){
$dayString = implode(",", $days);
$conditions[] = " FIND_IN_SET ($dayString, posts." . $intToCol[$int].")" ;
}
$add_here = "AND (" . implode(" OR ", $conditions) . ")";
}else if(($avail != "")&&($size == 1))
{
foreach($avail as $k=>$v)
{
$v;
$array = explode('-', $v);
$day =$array[0]; // Wed
$column = $array[1]; // 2
if($column == 1)
{
$col = "morning";
}
if($column == 2)
{
$col = "afternoon";
}
if($column == 3)
{
$col = "evening";
}
}
$add_here = " posts.".$col." = '".$day."' ";
$sql = "SELECT * , (3956 * 2 * ASIN(SQRT( POWER(SIN(('$lat' - lat) * pi()/180 / 2), 2) +COS('$lat' * pi()/180) * COS(lat * pi()/180) * POWER(SIN(('$lon' - lon) * pi()/180 / 2), 2) ))) as distance from posts WHERE posts.subname LIKE '%$subject%' AND posts.pricing <= '$rate' ".$add_here."".$IsTutionCentre." GROUP BY posts.UUID having distance <= '$distance' order by distance";
$stmt =connection::$pdo->prepare($sql);
$stmt->execute();
$place=array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$place[] = $row;
}
$_SESSION['subject'] = $place;
//send back to ajax call made page
echo json_encode($place);
}
?>
Upvotes: 0
Views: 46
Reputation: 24002
afternoon = 'Thrs,Fri,Sat,Sun';
evening = 'Thrs,Fri,Sat,Sun';
When a set of values are stored as csv in a single row field, use of 'IN'
is not going to work. You have to use 'FIND_IN_SET
'
Change:
AND (posts.afternoon IN ('Sat') OR posts.evening IN ('Sat'))
To:
AND ( FIND_IN_SET( 'Sat', posts.afternoon )
OR FIND_IN_SET( 'Sat', posts.evening ) )
You can apply the same for other day occurrences.
Documentation Reference:
FIND_IN_SET(str,strlist)
:
Upvotes: 1