Selecting large amount of rows from database table with MySQL - php

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/>";
}

Related

How to query all fields in a row

I know this is very simple, but I haven't used PHP/MySQL in a while and I have been reading other threads/php website and can't seem to get it.
How can I query a single row from a MySQL Table and print out all of the fields that have data in them? I need to exclude the NULL fields, and only add those that have data to an html list.
To clarify, I would like to display the field data without specifying the field names, just for the reason that I have a lot of fields and will not know which ones will be NULL or not.
What you've outlined requires 4 basic steps:
Connect to the database.
Query for a specific row.
Remove the null values from the result.
Create the html.
Step 1 is quite environment specific, so that we can safely skip here.
Step 2 - SQL
SELECT * from <tablename> WHERE <condition isolating single row>
Step 3 - PHP (assuming that $query represents the executed db query)
//convert the result to an array
$result_array = mysql_fetch_array($query);
//remove null values from the result array
$result_array = array_filter($result_array, 'strlen');
Step 4 - PHP
foreach ($result_array as $key => $value)
{
echo $value \n;
}
Just SELECT * FROM table_name WHERE.... will do the trick.
To grab data from specific fields, it would be SELECT field_1,field_2,field_3....
you have to make a string which represent mysql query. Then there is function in php named mysql_query(). Call this function with above string as parameter. It will return you all results. Here are some examples
You need to do it like this...
First connect to your sql... Reference
Now make a query and assign it to a variable...
$query = mysqli_query($connect, "SELECT column_name1, column_name2 FROM tablename");
If you want to retrieve a single row use LIMIT 1
$query = mysqli_query($connect, "SELECT column_name1, column_name2 FROM tablename LIMIT 1");
If you want to fetch all the columns just use * instead of column names and if you want to leave some rows where specific column data is blank you can do it like this
$query = mysqli_query($connect, "SELECT * FROM tablename WHERE column_name4 !=''");
Now fetch the array out of it and loop through the array like this..
while($show_rows = mysqli_fetch_array($query)) {
echo $show_rows['column_name1'];
echo $show_rows['column_name2'];
}
If you don't want to include the column names in the while loop, you could do this:
while($show_rows = mysqli_fetch_array($query)) {
foreach( $show_rows as $key => $val )
{
echo $show_rows[$key];
}
}

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 row selection

I have a table as below,
ID Name Age
----------------------
100 A 10
203 B 20
Now how do i select only row1 using MySQL SELECT command and then I've to increase +1 to it to select row2. In short I'll be using for loop to do certain operations.
Thanks.
Sounds like you've got a mix up. You want to select all the rows you want to iterate through in your for loop with your query, and then iterate through them one by one using php's mysql functions like mysql_fetch_row
You should not try to use tables in a linear fashion like this. Set your criteria, sorting as appropriate, and then to select the next row use your existing criteria and limit it to one row.
SELECT * FROM `table` ORDER BY `ID` LIMIT 1
SELECT * FROM `table` ORDER BY `ID` WHERE ID > 100 LIMIT 1
You'd probably be better off retrieving all rows that you need, then using this. Note the LIMIT is entirely optional.
$query = mysql_query(' SELECT ID, Name, Age FROM table_name WHERE condition LIMIT max_number_you_want '))
while ($row = mysql_fetch_assoc($query)
{
// Do stuff
// $row['ID'], $row['Name'], $row['Age']
}
Lots of small queries to the database will execute much slower than one decent-sized one.
You should get the result into an array (php.net : mysql_fetch_*).
And after you'll can loop on the array "to do certain operations"
Yep, this is a pretty common thing to do in PHP. Like the others who have posted, here is my version (using objects instead of arrays):
$result = mysql_query("SELECT * FROM table_name");
while ($row = mysql_fetch_object($result)) {
// Results are now in the $row variable.
// ex: $row->ID, $row->Name, $row->Age
}

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.

Summing a field from all tables in a database

I have a MySQL database called "bookfeather." It contains 56 tables. Each table has the following structure:
id site votes_up votes_down
The value for "site" is a book title. The value for "votes_up" is an integer. Sometimes a unique value for "site" appears in more than one table.
For each unique value "site" in the entire database, I would like to sum "votes_up" from all 56 tables. Then I would like to print the top 25 values for "site" ranked by total "votes_up".
How can I do this in PHP?
Thanks in advance,
John
You can do something like this (warning: Extremely poor SQL ahead)
select site, sum(votes_up) votes_up
from (
select site, votes_up from table_1
UNION
select site, votes_up from table_2
UNION
...
UNION
select site, votes_up from table_56
) group by site order by sum(votes_up) desc limit 25
But, as Dav asked, does your data have to be like this? There are much more efficient ways of storing this kind of data.
Edit: You just mentioned in a comment that you expect there to be more than 56 tables in the future -- I would look into MySQL limits on how many tables you can UNION before going forward with this kind of SQL.
Here's a PHP code snip that should get it done.
I have not tested it so it might have some typos and stuff, make sure you replace DB_NAME
$result = mysql_query("SHOW TABLES");
$tables = array();
while ($row = mysql_fetch_assoc($result)) {
$tables[] = '`'.$row["Tables_in_DB_NAME"].'`';
}
$subQuery = "SELECT site, votes_up FROM ".implode(" UNION ALL SELECT site, votes_up FROM ",$tables);
// Create one query that gets the data you need
$sqlStr = "SELECT site, sum(votes_up) sumVotesUp
FROM (
".$subQuery." ) subQuery
GROUP BY site ORDER BY sum(votes_up) DESC LIMIT 25";
$result = mysql_query($sqlStr);
$arr = array();
while ($row = mysql_fetch_assoc($result)) {
$arr[] = $row["site"]." - ".$row["sumVotesUp"];
}
print_r($arr)
The UNION part of Ian Clelland answer can be generated using a statement like the following. The table INFORMATION_SCHEMA.COLUMNS has a column TABLE_NAME to get all tables.
select * from information_schema.columns
where table_schema not like 'informat%'
and column_name like 'VOTES_UP'
Join all inner SELECT with UNION ALL instead of UNION. UNION is doing an implicit DISTINCT (on oracle).
The basic idea would be to iterate over all your tables (using a SQL SHOW TABLES statement or similar) in PHP, then for every table, iterate over the rows (SELECT site,votes_up FROM $table). Then, for every row, check the site against an array that you're building with sites as keys and votes up as values. If the site is already in the array, increment its votes appropriately; otherwise, add it.
Vaguely PHP-like pseudocode:
// Build an empty array for use later
$votes_array = empty_array();
// Get all the tables and iterate over them
$tables = query("SHOW TABLES");
for($table in $tables) {
$rows = query("SELECT site,votes_up FROM $table");
// Iterate over the rows in each table
for($row in $rows) {
$site = $row['site'];
$votes = $row['votes_up'];
// If the site is already in the array, increment votes; otherwise, add it
if(exists_in_array($site, $votes_array)) {
$votes_array[$site] += $votes;
} else {
insert_into_array($site => $votes);
}
}
}
// Get the sites and votes as lists, and print out the top 25
$sorted_sites = array_keys($votes_array);
$sorted_votes = array_values($votes_array);
for($i = 0; $i < 25; $i++) {
print "Site " . $sorted_sites[$i] . " has " . $sorted_votes[$i] . " votes";
}
"I allow users to add tables to the database." - I hope all your users are benevolent and trustworthy and capable. Do you worry about people dropping or truncating tables, creating incorrect new tables that break your code, or other things like that? What kind of security do you have when users can log right into your database and change the schema?
Here's a tutorial on relational database normalization. Maybe it'll help.
Just in case someone else that comes after you wants to find what this could have looked like, here's a single table that could do what you want:
create database bookfeather;
create user bookfeather identified by 'bookfeather';
grant all on bookfeather.* to 'bookfeather'#'%';
use bookfeather;
create table if not exists book
(
id int not null auto_increment,
title varchar(255) not null default '',
upvotes integer not null default 0,
downvotes integer not null default 0,
primary key(id),
unique(title)
);
You'd vote a title up or down with an UPDATE:
update book set upvotes = upvotes + 1 where id = ?
Adding a new book is as easy as adding another row:
insert into book(title) values('grails in action')
I'd strongly urge that you reconsider.

Categories