I am using this function to list items from table helps depending on parameters: (I included most of code but you can really just focus on the mysql querys)
function list_helps($by,$value,$page = -1,$ipp = 20){
/* Yes I concatenate querys... so i use some variables to help it a bit */
$sql = 'SELECT helps.* FROM helps ';
$where = ''; $orderBy = ''; $in = ''; $join = ''; $limit = ''; $resultitems = ''; $header = '';
if($page > 0) $limit = 'LIMIT '.$page*$ipp.', '.($page+1)*$ipp; else $limit = 'LIMIT 10';
switch($by){
case 'byuser':
$where = 'WHERE id_user ='.$value;
$orderBy = 'ORDER BY id DESC';
break;
case 'byfriend':
$sql = 'SELECT
h.*,
f.*
FROM (
SELECT
id,
CASE followerid WHEN '.$value.' THEN followingid ELSE followerid END AS friend_id
FROM friends
WHERE acepted = 1
AND (followerid = '.$value.' OR followingid = '.$value.')
) AS f
INNER JOIN helps AS h ON h.id_user = f.friend_id
ORDER BY h.id DESC';
break;
default:
break;
}
$sql .= $where.' '.$orderBy.' '.$limit;
$res = cache_query($sql,'',60*60*5);
/* checks in cache first, if not; executes query.. next code it's to render content */
}
There are more cases but lets focus on those two.
They both serve the 'helps' that are being requested (if user, or if users's friend); The problem is when i am trying to retrieve the comments of those (like if it where a blog post); which I am doing like so:
res = cache_query('SELECT help_replies.content, help_replies.date,
help_replies.offers, help_replies.accepted, help_replies.id_responds,
usuarios.first_name, usuarios.last_name, usuarios.avatar,usuarios.id
FROM help_replies left join usuarios
ON help_replies.id_user = usuarios.id
WHERE help_replies.id_responds = '.$this->id.'
ORDER BY help_replies.id ASC', '', 30);
foreach($res as $obj) {
/* $obj['id_responds'] */
}
}
The thing is that the help_replies.id_responds makes reference to the item, so when the case is 'byuser' is fine; but when the case is 'byfriend' this field is lost (so is showing always the same comments)
Conclusion:
byuser -> helps fine & comments fine
byfriend -> helps fine (which is wierd) & comments wrong
Any Idea why $this->id is not as expected from the (JOINED) query?
-EDIT-
$this->id comes from this construct method (i ommited many atributes)
function __construct($item) {
$this->id = $item['id'];
$this->id_user = $item['id_user'];
..
}
And $item is one iteration of the foreach (so its the returned row converted to array)
Muchas Gracias
Your byfriends query executed by function list_helps(...) appears to return a field labelled id twice; once for your helps table and then again for f the alias of the friends table, as part of the sub-query.
I can imagine that if $this->id contains a friends id and not the helps id then your comments query (help_replies) will return the wrong results.
So perhaps changing your sub-query with an alias for the friends id as shown ie id AS friendsId, everything will work as expected?
function list_helps($by,$value,$page = -1,$ipp = 20){
...
...
case 'byfriend':
$sql = 'SELECT
h.*,
f.*
FROM (
SELECT
id AS friendsId,
CASE followerid WHEN '.$value.' THEN followingid ELSE followerid END AS friend_id
FROM friends
WHERE acepted = 1
AND (followerid = '.$value.' OR followingid = '.$value.')
) AS f
INNER JOIN helps AS h ON h.id_user = f.friend_id
ORDER BY h.id DESC';
break;
I've got into the habit of naming my table identifier field <tablename>Id for this very reason and saves having to use alias everywhere.
Related
orderfood
orderfood_id food_id total_amount
foodcancel
foodcancel_id food_id status
$query = $this->db->query("SELECT * FROM order_food of LEFT JOIN `foodcancel` fc ON of.food_id = fc.food_id WHERE of.orderfood_id = '" . (int)$orderfood_id . "'");
$order_foods = $query->rows;
above is my query, what i wanted is that if there food_id inside foodcancel table , exclude it from rows, possbile to do it ?
For exclude the existing values you could try checking null for corresponding matching value
SELECT *
FROM order_food of
LEFT JOIN foodcancel fc ON of.food_id = fc.food_id
and of.food_id = your_value
WHERE fc.orderfood_id is null
anyway you should not php var in your sql code because in this way you are are risk for sqlinjection for avoid this you should take a look at prepared statement and binding param
It's very possible to do. In my logic. first, you must get all food_id on food_cancel table. Then save it into variabel and use it when you show orderFood table with adding NOT IN condition.
I've write code for you,
<?php
// Get Food Id From Cancel
$orderCancel = mysqli_query($mysqli, "SELECT * FROM `foodcancel`");
$cancelId = "";
while ($cancel = mysqli_fetch_array($orderCancel)) {
$cancelId .= $cancel["food_id"].",";
};
$cancelId = substr($cancelId, 0, -1);
// Put Food Id on Cancel Table into NOT IN Condition Database
$orderFood = mysqli_query($mysqli, "SELECT * FROM `orderfood` WHERE food_id NOT IN ($cancelId)");
while ($order = mysqli_fetch_assoc($orderFood)) {
$food[] = $order;
};
echo json_encode($food);
?>
I have a database structure something like the following:
Table A: PersonId, GroupId
Table B: GroupId, ParentGroupId
Given a PersonId, I want to find the Ids of all people in parent groups of that person's group.
First I select the ParentGroupId for the given PersonId, by joining with B. Then I do a while loop, selecting and recording the PersonId from A based on the GroupId returned in the previous search, and continue the loop by obtaining the next ParentGroupId from B.
Is this an efficient way to do this search, or is there an option that does not involve a while to "bubble up" in this manner?
(this is a simplified version of the actual scenario, changing the schema is not an option)
$sql = 'SELECT ParentGroupID FROM A WHERE PersonId = ' . $id;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupId'];
if(!is_null($parent_group)) {
$parent_ids = array();
while($parent_group > 0) {
//is there a way to do this where I retrieve all managers <= lvl 6 at once, so I don't have to loop in order to 'tier up'?
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID = ' . $parent_group;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupID'];
$parent_ids[] = $row['PersonID'];
}
}
Combining your two queries into one would be more efficient:
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID IN (
SELECT ParentGroupID FROM A WHERE ParentGroupID > 0
AND PersonId = ' . $id .')' ;
I have the following tables:
tbl_users
===============
uid
username
password
gid
tbl_groups
===============
gid
name
type
I am trying to figure out how to use the sqlmapper in f3 to be able to query both tables where username equals $_POST["username"] and be able to get the group name and type as well. Is it possible to join like queries using this framework with sqlmapper?
I've been searching around and can't find any examples on that.
you can try to setup some virtual fields for this:
$mapper->group_name = 'select name from tbl_groups where tbl_groups.gid=tbl_users.gid';
$mapper->group_type = 'select type from tbl_groups where tbl_groups.gid=tbl_users.gid';
$mapper->load(array('uid = ?',123));
echo $mapper->group_name;
Here is the example with {VIEW}:
I have implemented here pagination with SQL Mapper using View view_user_list_with_referral
$dropInstantWinnerView = $this->db->exec("DROP VIEW IF EXISTS view_user_list_with_referral;");
$createInstantWinnerView = $this->db->exec("CREATE VIEW view_user_list_with_referral AS SELECT u.fb_id, fb_link, name, r.referred_by, u.created FROM users u LEFT OUTER JOIN referral r ON u.fb_id=r.joinee ");
$user = new \DB\SQL\Mapper($this->db,'view_user_list_with_referral');
$limit = 20;
$page = Pagination::findCurrentPage();
$order_condition = F3::get("PARAMS.order_condition");
$order_class= "";
if(!empty($order_condition)){
$cond = explode(":", $order_condition);
$option = array('order' => $cond[0].' '.$cond[1]);
if($cond[1]=='ASC'){
$order_condition = $cond[0].':DESC';
$order_class = ":DESC";
}else{
$order_condition = $cond[0].':ASC';
$order_class = ":ASC";
}
}else{
$option = array('order' => 'created DESC');
}
$subset = $user->paginate($page-1, $limit, null, $option);
$pages = new Pagination($subset['total'], $limit);
$pages->setTemplate("admin/pagebrowser.html");
F3::set('pagebrowser', $pages->serve());
//echo "<pre>";print_r($subset);exit;
F3::set('page', $page);
F3::set('order_condition', $order_condition);
F3::set('total_found_records', $user->count());
I hope it will save someones time :)
I would like to add a value to each row that I get from my query depending on if a row exist in another table. Is there a smart way to achieve this?
This is the code I have:
$sth = mysql_query("SELECT tbl_subApp2Tag.*, tbl_tag.* FROM tbl_subApp2Tag LEFT JOIN tbl_tag ON tbl_subApp2Tag.tag_id = tbl_tag.id WHERE tbl_subApp2Tag.subApp_id = '".$sub."' ORDER BY tbl_tag.name ASC");
if(!$sth) echo "Error in query: ".mysql_error();
while($r = mysql_fetch_assoc($sth)) {
$query = "SELECT * FROM tbl_userDevice2Tag WHERE tag_id='".$r['id']."' AND userDevice_id='".$user."'";
$result = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($result)) {
$r['relation'] = true;
$rows[] = $r; //Add 'relation' => true to this row
} else {
$r['relation'] = false;
$rows[] = $r; //Add 'relation' => false to this row
}
}
print json_encode($rows);
Where the //Add ... is, is where I would like to insert the extra value. Any suggestions of how I can do this?
I'm still a beginner in PHP so if there are anything else that I have missed please tell me.
EDIT: Second query was from the wrong table. This is the correct one.
Edited Edited below query to reflect new information because I don't like leaving things half-done.
$sth = mysql_query("
SELECT
tbl_subApp2Tag.*,
tbl_tag.*,
ISNULL(tbl_userDevice2Tag.userDevice_id) AS relation
FROM tbl_subApp2Tag
LEFT JOIN tbl_tag
ON tbl_tag.id = tbl_subApp2Tag.tag_id
LEFT JOIN tbl_userDevice2Tag
ON tbl_userDevice2Tag.tag_id = tbl_tag.id
AND tbl_userDevice2Tag.userDevice_id = '".$user."'
WHERE tbl_subApp2Tag.subApp_id = '".$sub."'
ORDER BY tbl_tag.name ASC
");
Though the above feels like the LEFT JOIN on tbl_tag is the wrong way around, but it's hard to tell as you are vague on your eventual aim. For example, if I was to assume the following
Tags will always exist
subApp2Tag will always exist
You want to know if a record in tbl_userDevice2Tag matches the above
Then I would do the following instead. The INNER JOIN means that it won't worry about records in tbl_tag that are not on the requested subApp_id which in turn will limit the other joins.
$sth = mysql_query("
SELECT
tbl_subApp2Tag.*,
tbl_tag.*,
ISNULL(tbl_userDevice2Tag.userDevice_id) AS relation
FROM tbl_tag
INNER JOIN tbl_subApp2Tag
ON tbl_subApp2Tag.tag_id = tbl_tag.id
AND tbl_subApp2Tag.subApp_id = '".$sub."'
LEFT JOIN tbl_userDevice2Tag
ON tbl_userDevice2Tag.tag_id = tbl_tag.id
AND tbl_userDevice2Tag.userDevice_id = '".$user."'
ORDER BY tbl_tag.name ASC
");
you have to do all the job in a single query.
Why can't you just $r['append'] = "value"; before adding $r to the array?
I have an app that uses the codeigniter CXTags tagging library.
The database structure is as follows:
posts
id
tags_ref
row_id
table
tag_id
tags
id
safe_tag
tag
My query basically goes if $safe_tag is not null then join tags_ref on post.id = tags_ref.row_id, join tags on tags_ref.tag_id = tags.id, where tags_ref.table = 'posts' and tags.safe_tag = 'food'
SELECT * FROM posts
JOIN tags_ref ON posts.id = tags_ref.row_id
JOIN tags ON tags_ref.tag_id = tags.id
WHERE tags.safe_tag = $safe_id
Unfortunately the query I've written in active record is not functioning properly. The query works perfectly when £safe_tag is null but when it's not I get wrong results.
function get_posts($id = NULL, $safe_tag = NULL) {
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
}
//if an id was supplied
if ( $id != NULL ) {
$this->db->where('posts.city_id',$id);
}
// execute query
$query = $this->db->get('posts');
...
Here is the query with profiling on:
SELECT *
FROM (`posts`)
INNER JOIN `tags_ref` ON `posts`.`id` = `tags_ref`.`row_id`
INNER JOIN `tags` ON `tags_ref`.`tag_id` = `tags`.`id`
WHERE `tags_ref`.`table` = 'posts'
AND `tags`.`safe_tag` = 'food'
AND `posts`.`city_id` = '2'
Can someone have a look? I think I need a fresh set of eyes on it.
Your forgot to actually run the query inside your first if{}
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
$this->db->get(); // here
}