Record query results for use in further queries - php

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)

Related

Incrementing via MySQL/PHP

I am looking for a way to increment and decrement by a step of three records in a table and return them.
Say ID '4' is currently active. I want to get the next 3 and the previous 3 records with IDs and category of 3.2.1 and 5.6.7 (via incrementing and decrementing).
So far I have:
$stmt = $db->query("SELECT id, category FROM test");
$stmt->execute();
while ($results = $stmt->fetch(PDO::FETCH_ASSOC))
{
$current = $results['id'];
$category = $results['category'];
$next = array(array(
'slide_no' => $current,
'category' => $category
));
}
print_r($next);
Using this, I am getting back every row in the table.
I'm getting confused how to increment and decrement the records by a step of 3 and make sure that the category will also increment accordingly.
Thank you very much.
You will need to create a string with the 6 ids that you need.
So if CatID was 4 you would want
$selectIDs = '1, 2, 3, 4, 5, 6, 7";
Then when you perform your SQl you would use
"SELECT id, category FROM test WHERE id IN (" . $selectIDs ."')";
If I understand your question correctly, you want to paginate the displayed data. You need to use the MySQL LIMIT clause.
You'll need to adjust your query, using values generated from your code. See an example below:
$stmt = $db->query("SELECT id, category FROM test LIMIT ?, 3");
#you'll supply the ? parameter depending on your current start index
MySQL Limit clause Tutorial
You can use the => and <= operators.
First store the id in a variable:
$intId = 4
Then add and decrement 3
$intAdd = $intId + 3
$intDecr = $intId -3
Then setup your sql string
$stmt = $db->query('SELECT id, category FROM test where id =>'. $intDecr.' and <= '.$intAdd. ');

Checking if a value is in the db many times

I have a table A, with just two columns: 'id' and 'probably'. I need to go over a long list of ids, and determine for each one whether he is in A and has probability of '1'. What is the best way to do it?
I figured that it would be best to have 1 big query from A in the beginning of the script, and after that when I loop each id, I check the first query. but than i realized I don't know how to do that (efficiently). I mean, is there anyway to load all results from the first query to one array and than do in_array() check? I should mention that the first query should had few results, under 10 (while table A can be very large).
The other solution is doing a separate query in A for each id while I loop them. But this seems not very efficient...
Any ideas?
If you have the initial list of ids in array, you can use the php implode function like this:
$query = "select id
from A
where id in (".implode (',', $listOfIds).")
and probability = 1";
Now you pass the string as first parameter of mysql_query and receive the list of ids with probability = 1 that are within your initial list.
// $skip the amount of results you wish to skip over
// $limit the max amount of results you wish to return
function returnLimitedResultsFromTable($skip=0, $limit=10) {
// build the query
$query = "SELECT `id` FROM `A` WHERE `probability`=1 LIMIT $skip, $limit";
// store the result of the query
$result = mysql_query($query);
// if the query returned rows
if (mysql_num_rows($result) > 0) {
// while there are rows in $result
while ($row = mysql_fetch_assoc($result)) {
// populate results array with each row as an associative array
$results[] = $row;
}
return $results;
} else {
return false;
}
}
for each time you call this function you would need to increment skip by ten in order to retrieve the next ten results.
Then to use the values in the $results array (for example to print them):
foreach ($results as $key => $value) {
print "$key => $value <br/>";
}
Build a comma separated list with your ids and run a query like
SELECT id
FROM A
WHERE id IN (id1, id2, id3, ... idn)
AND probability = 1;
Your first solution proposal states that:
You will query the table A, probabyly using limit clause since A is a table with large data.
You will place the retrieved data in an array.
You will iterate through the array to look for the id's with probability of '1'.
You will repeat the first three steps several times until table A is iterated fully.
That is very inefficient!
Algorithm described above would require lots of database access and unneccessary memory (for the temporary array). Instead, just use a select statement with 'WHERE' clause and process with the data you want.
You need a query like the following I suppose:
SELECT id, probably FROM A WHERE A.probably = 1
If i understood you correctly, you should filter in the SQL query
SELECT * FROM A WHERE A.probably = 1

MySQL: Join (2 tables) vs single queries (1 table)

In PHP, I have an array of 11 persons where just the ID of each person is given:
$persons = array(1, 3, 39, 72, 17, 20, 102, 99, 77, 2, 982);
In my MySQL database, there's a table containing detailed information about each person:
TABLE personInfo
- ID (integer)
- name (string)
- birth date (timestamp)
- weight (decimal)
- ...
PROBLEM:
So now, I want to select the matching name for each ID in the PHP array. I can only imagine two solutions to do this:
1. for-loop:
foreach ($persons as $person) {
$result = mysql_query("SELECT name FROM personInfo WHERE id = ".$person);
}
2. logical operator OR
$result = mysql_query("SELECT name FROM personInfo WHERE id = 1 OR id = 3 OR id = 39 OR ...");
Both solutions are slow, aren't they?
But if I had another MySQL table containing the IDs of the PHP array ...
TABLE ids
- ID (integer)
... I could use a join to make a really fast MySQL query, right?
$result = mysql_query("SELECT a.ID, b.name FROM ids AS a JOIN personInfo AS b ON a.ID = b.ID");
QUESTION:
Is all this correct so far? If yes: Why is this so? The MySQL query is faster if I have a second table? With only one table it is incredibly slow? What is the fastest way to solve my problem (selecting the names matching the IDs of the PHP array)?
If you have lots of ids (several hundreds or more), feeding the values into a temporary table and joining it is actually faster.
You may want to read this article:
Passing parameters in MySQL: IN list vs. temporary table
IF you have ID's you should just query the Id's you have. So
$result = mysql_query("SELECT name FROM personInfo WHERE id = 1 OR id = 3 OR id = 39 OR ...");
would be right, although I would use
$result = mysql_query("SELECT name FROM personInfo WHERE id IN (1,2,3,4....) )

sort an $array of ints by repetition and remove repetitions

i need to do this in php
lets say i have [1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,5,5,5,5,5,5,5,5,5,5,9,9,9,9,9]
i would like [1,5,9,2,3,4]
but my situation its a bit different, it's result from a mysql query
i have only an asociative atribute 'id_deseada', so i do now
while($row = mysql_fetch_array($result){
$t = $row['id_deseada'];
}
so instead of that, i guess i'd have to do domething like the first example; sort $result ordered by times of repetition and maybe beetter in a new array with a new field 'count' ?
This all begins because of this query:
SELECT articles.id as id_deseada,tags.* FROM articles,tags WHERE tags.id_article = articles.id AND tags.name IN ('name one','name two','form search inputs','...)
the problem is that returns one result for every tag and i want on result for every article..
First, generate the value array like this:
$vals = array();
while($row = mysql_fetch_array($result){
$vals[] = $row['id_deseada'];
}
Then, count and sort:
$valCounts = array_count_values($vals);
arsort($valCounts);
$result = array_keys($valCounts);
You can actually do it using an SQL query. For example, we have this table:
create table lol (id_deseada int);
insert into lol values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(2),(3),(4),(5),(5),(5),(5),(5),(5),(5),(5),(5),(5),(5),(9),(9),(9),(9),(9);
You can select the id_deseada's from the database sorting by repetitions by using grouping and ordering.
SELECT id_deseada FROM lol
GROUP BY id_deseada
ORDER BY COUNT(*) DESC
Result: 1, 5, 9, 2, 3, 4.

Selecting large amount of rows from database table with MySQL

I have a table with attributes like this:
likes(id, message, ip, time)
id is the primary key and is auto-incrementing. Whet I want to do is select 30 rows from this table based on an id that I provide.
I can build a random array of all IDs I want to grab from the table, now I just need to go about doing that. My usual SQL query would be:
SELECT message
FROM `likes`
WHERE id=$id
LIMIT 1
But I need to select 30 rows. There are two ways I can do this, I can either use a FOR loop with 30 queries, or combine it all into one query and grab them all at the same time. Obviously I would like to do the latter.
Can anyone help me out on the SQL query to use to grab more than one row from my database table at once? And perhaps an example of how I would parse these into an array for easy retrieval?
Greatly appreciated, thanks.
You could use the IN operator, so it would be something like this:
SELECT message FROM likes WHERE id IN (1, 2, 3, 4, 5, ...)
$ids = array(1,2,3,4,5,6,7,8,9); //or however many
$query = "SELECT * FROM `likes` WHERE `id` IN (".implode(', ', $ids).")";
$res = mysql_query($query);
$results = array();
while($tmp = mysql_fetch_array($res)) {
$results[$tmp['id'] = $tmp;
}
Will give you an array, $results, sorted by key ['id'], with each being an array on each answer key-- 'id', 'message', 'ip', 'time'. So for example:
for($results as $key => $val) {
echo "${val['ip']} posted {$var['message']} on {$val['time']} <br/>";
}

Categories