PHP variable variables with mysql resultset - php

So I have a mysql table which has a id column (sid) that can be dynamically added to. Now I am doing a query to get count of all entries grouped into each of these sid's like so:
SELECT SUM(IF(sid = 71, 1, 0)) as count71,
SUM(IF(sid = 72, 1, 0)) as count72,
SUM(IF(sid = 75, 1, 0)) as count75,
SUM(IF(sid = 81, 1, 0)) as count85
FROM `table`
WHERE userid=44;
Note that all the SUM fields are created dynamically and I don't know what the actual sid's are. Now question is how do I loop through the resultset for each of the counts using PHP's variable variables? I've tried this but doesn't work.
$count_var = "rs['count71']"
$$count_var // holds number of entries where sid is 71;
Thanks!

May I suggest this instead:
select sid, count(*) from `table` where userid = 44 group by sid ;

You could do:
$count_var = "rs['count71']";
echo eval('return $'. $count_var . ';');
but of course #troelskn's answer is probably the best solution for what you want

Related

Record query results for use in further queries

I can't explain it properly but I have several different loop queries on a page (news website homepage) to select articles and want to "record" the ID of each article to exclude such ID's from further query results.
Select rand from database ... result = ID's 3, 99, 6
$selected = 3, 99, 6
Select rand from database WHERE ID != $selected ... result = ID 51
$selected = 3, 99, 6, 51
Select rand from database WHERE ID != $selected ... result = ID 4
I can't wrap my head around on how to "record" the already selected ID's incremential and then use it further down to prevent the same article to appear twice.
make an array where you add all result ids into, then explode that array for the next sql. something like this:
$selectedIds = array();
// make first query, get results in loop. im not writing the query execution here, just the loop after
while($row = mysqli_fetch_assoc($res)){
$selectedIds[] = $row['id'];
// do your other stuff here (single article generation)
}
// for further queries you can make the WHERE clause like this
$query = "SELECT rand FROM table WHERE ID not in (".explode(', ', $selectedIds).")";
// this will make the actual query look like this:
// SELECT rand FROM table WHERE ID not in (3, 99, 6)

Updating more than one row with a single query

I have a table called posts in my database with a column called has_read. I then have an array of post IDs like so:
$posts = array(1, 5, 29, 38, 50, 51, 52, 65, 79);
What I want to do is for all of those posts in the array, update their row to add the user ID to has_read. I can't use a foreach loop because it'll execute 9 queries, which I think is too much.
$updatestring = implode(",",$posts = array(1, 5, 29, 38, 50, 51, 52, 65, 79))
$sql = "UPDATE post SET has_read=1 WHERE userID IN($updatestring)";
Concat your array of id's to a comma separated string and just use the IN() function for a bulk update
Although actually thinking about it this is the completely wrong way of doing this. Since its a one thread to many users relationship you're better off having a normalised database for this and using a separate table to track reads based off userid and thread id.
You can use WHERE IN statment like this :
$result = mysql_query('UPDATE table SET field = value WHERE id IN ('.implode(',',$posts).')');
You can use IN.
$sql = "UPDATE posts
SET has_read = has_read + " . $user_id . "
WHERE id IN (" . implode(",", $posts) . ")";
Of course, you should not literally do it this way, but prepare a statement and pass the $user_id as a parameter, depending on the database library you are using.
use Where with IN
$result = mysql_query('UPDATE posts SET has_read= user_id
WHERE id IN ('.implode(',',$posts).')');
What about something like:
UPDATE posts_table SET has_read = 1 WHERE id IN (1, 5, 29, 38, 50, 51, 52, 65, 79);
Try this:
$query = 'UPDATE posts SET has_head = 1 WHERE id IN (' . implode(',', array_map('intval', $array)) . ');';

How do I translate this raw SQL query in PHP ActiveRecord?

I'm trying to run this sql query as a php activerecord query:
delete from article_categories where
article_id = 10
and
category_id in (1,4,5,6,7)
This statement works fine when I run it from the mysql console.
I tried doing this from php activerecord:
$query["conditions"] = array('article_id = ? and category_id in (?)', 10, "1,4,5,6,7");
ArticleCategory::delete_all($query);
The problem is it is only deleting one record at a time.
I expect all the records that match
article_id == 3
and
category_id == 1 || category_id == 2 || ... || category_id == 5
to be deleted.
However only the first record with fields
article_id = 3, category_id = 1
gets deleted.
What am I typing wrong?
If you want to use "IN (?)" in your where clause, be sure to pass an array as the condition value. Otherwise it would just read IN ("1,2,3,4") in stead of IN (1,2,3,4) (note the double quotes in the former version!).
So, it would look something like this:
$article_id = 1;
$categories = array(1, 2, 3, 4);
ModelName::delete_all(array(
'conditions' => array('article_id = ? and category_id IN (?)', $article_id, $categories)
));
And if you just want to delete the current record, do:
$record->delete();
Be careful not to invoke ->save() afterward, because the record will be saved again.
I'm not really sure if the ID you're sending it to delete can be empty? The documentation shows this for "Massive Update or Delete".
Post::table()->delete(array('id' => array(5, 9, 26, 30));
So, translated in your situation that would be something like
ArticleCategory::delete(array(array('id' => array(1, 4, 5, 6, 7)),
'conditions'=> array('article_id = ?', 10),
));

mysql - check if a group of elements are included in another group

I have the following setup:
An array in php like this:
$arr = array(1, 2, 3, 4);
A query that looks like this:
SELECT `epicThing` FROM `epicTable` AS `epic`
WHERE
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
(<<<< HERE IS MY PROBLEM >>>>)
The subquery returns something like (1, 2, 3, 4, 5, 6, 7, 8, 9).
Now what I need to check is that each of the elements from the array is in that returned answer of the subquery.
Basically something like
SELECT `epicThing` FROM `epicTable` AS `epic`
WHERE
'1' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
)
AND
'2' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
)
AND
'3' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
).......
But for each element.
For simplicity let's assume that elements are always in order (because I will probably need to convert the array to string), if is not possible otherwise. But I would prefer a general solution if available.
What I DON'T want to do is to get data in php and check it there (this is only a really really small part of a huge query).
If I'm understanding your question correctly, I think this would be the easiest way for you to test that all IDs in your array match to a record in the database:
<?php
$myArray = array(1,2,3);
$myArrayCount = count($myArray);
// Convert array for the query
$queryArray = implode(",", $myArray);
SELECT COUNT(DISTINCT(YourTable.id)) AS count
FROM YourTable
WHERE YourTable.id IN ($queryArray)
HAVING count = $myArrayCount;
?>
Mysql will return empty results if the HAVING count = $myArrayCount; does not match the number of IDs you are checking for.

Sorting mysql query in php

I get from db rows in order 10, 12, 13, 21, 06, 02, 08
I need that this will be sorted like this: 02, 06, 08, 10, 12, 13, 21
Order by field ASC doesnt work i need. I tried remove zeros and then sort array, but no results. Any thoughts?
Omeri
sort(ARRAY) did the trick
$sql = "SELECT DISTINCT l, item, l, s FROM tr WHERE s = '".$_POST['size']."' AND type = '".$type."' ORDER BY l ASC";
$res = mysql_query($sql,$this->conn);
$type = '<option selected="selected" disabled="disabled"></option>';
while($row = mysql_fetch_array($res)){
$caption[] = $row;
}
sort($caption);
foreach($caption as $row) {
$length = substr($row['item'], strrpos($row['item'], '-') + 1);
$type .= '<option value="'.$length.'">'.$length.'</option>';
}
change the column type of those numbers to INT then u get them ordered.
i think you have your colum now as CHAR or VARCHAR
#Eric Petroelje I would use:
SELECT * FROM table ORDER BY CAST(col AS SIGNED) ASC
Or add zeros in front of all your numbers. For example, 1 becomes 0001 and 2 becomes 0002 that way you will have your zeros and they will also sort. Oh, I see that you have commented below that your are also using 02 and 2. So you can disregard this.
Or add an extra INT column with the correct order.
The sorting should be done via the MySQL server. If you aren't getting the proper order, then your query might be wrong. Another problem could be that you are storing your numbers as text or another data type?
However, to remove 0's in the beginning, you can cast the variable explicitly to a integer:
$numstring = (int)$realint;
Sounds like the data is stored in MySQL as a CHAR or VARCHAR, so when the column is ordered, it's ordering it like it's a string rather than a number.
Other than changing the type of the column to an INT, you could force MySQL to treat it as an integer for ordering (assuming all values in the column are numbers) like so:
SELECT fields
FROM mytable
ORDER BY CAST(col AS SIGNED)

Categories