Got a delete method which is not working ... can anybody figure out why it's returning 0? The item is present in the table.
public function deleteItem($item_id)
{
$userItemIDS = array();
$userItemIDS = $this->helperClass->userItemIDS();
if( !in_array($item_id, $userItemIDS) )
{
return false;
}
$q = $this->db->mysqli->prepare("DELETE i, s FROM items i
LEFT JOIN save_list s
ON i.id = s.item_id
WHERE i.id = ? AND s.item_id = ?
AND
NOT EXISTS (SELECT id FROM pending_wins WHERE item_id = ?)
AND
NOT EXISTS (SELECT id FROM bids WHERE item_id = ?)");
if($q)
{
$q->bind_param("iiii", $item_id, $item_id, $item_id, $item_id);
$a_r = $q->affected_rows;
$q->execute();
$q->close();
return $a_r;
}
}
The comments are very helpful and I appreciate them a lot. However my problem was in the query itself. Taking out AND s.item_id = ? deletes the
entry from the items table and fromsave_list if present.
$q = $this->db->mysqli->prepare("DELETE i, s FROM items i
LEFT JOIN save_list s
ON i.id = s.item_id
WHERE i.id = ?
AND
NOT EXISTS (SELECT id FROM pending_wins WHERE item_id = ?)
AND
NOT EXISTS (SELECT id FROM bids WHERE item_id = ?)");
Related
I have a query that returns close to a 1000 records. Using pagination, I'm showing a 100 records per page. Great...no problem. I can also sort by last name or first name in either ascending of descending order. ok so far. The first page returns records for last name starting with A to C. The problem I'm having is that when I click last name to descend I get records with last name starting with Z. The records at the end of my query, I want to get results going from C to A (what is shown on my first page...repeating the same functionality in each page.
Here is what I got...
$orderColumn = 'lastName';
$orderDirection = 'ASC';
if( isset($_POST["oc"]) && $_POST["oc"] !== '' ) { $orderColumn = $_POST["oc"]; }
if( isset($_POST["od"]) && $_POST["od"] !== '' ) { $orderDirection = $_POST["od"]; }
$per_page = 100;
$query = "SELECT * FROM table as t
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and t.interviewed = 0";
$result = $db->query($query);
$count = mysql_num_rows($result);
$total = ceil($count/$per_page);
if ($_GET['page']) {
$page = $_GET['page'];
}
$offset = (($page-1)*$per_page);
$query2 = "SELECT firstName as first, lastName as last FROM table
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and interviewed = 0 order by $orderColumn $orderDirection LIMIT $offset, $per_page";
$res = $db-> query($query2);
while($row = mysql_fetch_array($res)){
echo "<span style='display: inline-block; width: 15%;'>$row[first]</span>";
echo "<span style='display: inline-block; width: 15%;'>$row[last]</span>";
}
To what I was saying in comment.. BTW I'm on my mobile phone so this may be unformatted and or take a while...
Select what_you_need
From
( select your_inner_select
From table t
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and interviewed = 0 LIMIT $offset, $per_page
ORDER BY $orderColumn ASC
)t
order by $orderColumn $orderDirection
I have to output some products from table 'products', along with the lowest price from the table 'product_licenses', which is the only column I need from that table in this query.
However, when I try to use the sql function MIN(), my loop only runs through the code once and gets the first result and then it stops, so I am a bit lost here.
This is the query using min() :
$mysql->query("
SELECT pd.*, min(lc.price) AS price
FROM `products` AS pd, product_licenses AS lc
WHERE pd.`status` = '1' AND lc.product_id = pd.id
ORDER BY pd.`id` ASC
$limitQuery
");
I'm using this function to get the products, but this, unfortunately, fetches the highest price:
public function getAllProducts($start = 0, $limit = 0, $order = '`datetime` ASC') {
global $mysql;
$limitQuery = '';
if ($limit != 0) {
$limitQuery = " LIMIT $start,$limit ";
}
**// Not working if I use min() on lc.price**
$mysql->query("
SELECT pd.*, lc.price
FROM `products` AS pd, product_licenses AS lc
WHERE pd.`status` = '1' AND lc.product_id = pd.id
ORDER BY pd.`id` ASC
$limitQuery
");
if ($mysql->num_rows() == 0) {
return false;
}
$this->usersWhere = '';
$return = array();
while ($d = $mysql->fetch_array()) {
$categories = explode(',', $d['category_id']);
unset($d['category_id']);
foreach ($categories as $c) {
$c = trim($c);
if ($c != '') {
$d['category_id'][$c] = $c;
}
}
$return[$d['id']] = $d;
}
$this->foundRows = $mysql->getFoundRows();
return $return;
}
Add GROUP BY in your query. your current query returns only one result since your are using aggregate function (MIN) but not grouping it.
SELECT pd.col1,
pd.col2, min(lc.price) AS PRICE
FROM `products` AS pd
INNER JOIN product_licenses AS lc
ON lc.product_id = pd.id
WHERE pd.`status` = '1'
GROUP BY pd.col1, pd.col2, pd.col3
ORDER BY pd.`id` ASC
$limitQuery
PS: post the structure of your database with records. It will the community understands your question clearly :)
You have no group by clause in your query, so the query is returning the first row only.
SELECT pd.col1, pd.col2, pd.col3, min(lc.price) AS price
FROM `products` AS pd, product_licenses AS lc
WHERE pd.`status` = '1' AND lc.product_id = pd.id
group by pd.col1, pd.col2, pd.col3
ORDER BY pd.`id` ASC
$limitQuery
You'll need a GROUP BY in there, like so:
SELECT pd.*, min(lc.price) AS price
FROM `products` AS pd, product_licenses AS lc
WHERE pd.`status` = '1' AND lc.product_id = pd.id
GROUP BY pd.`id`
ORDER BY pd.`id` ASC
$limitQuery
Note that with MySQL, you only need to group by the id column even though you are selecting other columns from the products table.
function sum($nomId){
$sql = "SELECT SUM(nomDetCantidad) FROM table2 where Id = $nomId";
$Resultado=$this->ProcesaSQLQueryList($sql);
if($Resultado>0){
foreach($Resultado as $key => $valor){
$cantidadTotal = $valor[0];
}
}
if($Resultado=='null'){$cantidadTotal=0;}
$sql = "UPDATE table1 SET nomCantidadTotal=$cantidadTotal,nomActualizado = NOW() WHERE nomId= $nomId";
return $this->ProcesaSQLQueryUpdate($sql);
and this is the function I call
function ProcesaSQLQueryList($SQLQuery){
$row= array();
if(!$this->link_mysql) $this->link_mysql = conectarManager();
if($res = mysql_query($SQLQuery,$this->link_mysql)){
while($r = mysql_fetch_array($res)){
$row[] = $r;
}
mysql_free_result($res);
return $row;
}else{
$this->last_error = $SQLQuery . " - " . mysql_error();
return -1;
}
}
So I sum up whatever I have in a field table 2 with the foreign key of table 1 then my result gets updated to the table 1 field but if I delete the fields in table 2 result wont get updated to 0 any suggestions I'm pretty sure this is an easy one but can't seem to find it
$sql = "SELECT SUM(nomDetCantidad) FROM table2 where nominaId = $nomId";
$Resultado = $this->ProcesaSQLQueryList($sql);
if ($Resultado > 0) {
foreach ($Resultado as $key => $valor) {
$cantidadTotal = $valor[0];
}
}
if ($cantidadTotal == '') {
$cantidadTotal=0.00;
}
$sql = "UPDATE table1 SET nomCantidadTotal=$cantidadTotal,nomActualizado = NOW() WHERE nomId = $nomId";
return $this->ProcesaSQLQueryUpdate($sql);
There! It was sending me a blank variable xD but fixed and there are more suitable ways to do it, I agree with Spencer but if a client wants a red swing he has to get a red swing you know? :) thanks for the help guys!
If you need a zero returned when there are no "matching" rows in table2, then wrap the return expression in an IFNULL function.
SELECT IFNULL(SUM(nomDetCantidad),0) FROM table2 ...
You could significantly reduce the amount of code you have, reduce the number of roundtrips to the database, and improve performance by doing all this work in a single UPDATE statement. You can use either a correlated subquery or an OUTER JOIN:
-- using a correleated subquery
UPDATE table t1
SET t1.nomActualizado = NOW()
, t1.nomCantidadTotal =
( SELECT IFNULL(SUM(t2.nomDetCantidad),0) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = t1.nomID
)
WHERE t1.nomId = $nomId
-- using an OUTER JOIN
UPDATE table1 t1
LEFT
JOIN (SELECT t2.Id, SUM(t2.nomDetCantidad) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = $nomId
GROUP BY t2.Id
) s
ON s.Id = t1.nomID
SET t1.nomCantidadTotal = IFNULL(s.nomCantidadTotal,0)
, t1.nomActualizado = NOW()
WHERE t1.nomID = $nomId
It's not at all clear why you need to store this total on table1, when you could derive it from table2 whenever you need it, without storing that value on table1 at all...
SELECT t1.nomId
, IFNULL((SELECT SUM(t2.nomDetCantidad) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = t1.nomID
),0) AS nomCantidadTotal
FROM table1 t1
WHERE t1.nomId = $nomId
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.
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
}