I have created a question Here That I think is a little bloated. To skim down this question here is my requirements:
I need to create 3 mySQL queries that grab all information in that row so that I can format the information into one of HTML tables.
Here is the query that I have which selects everything:
$qry_questions = mysql_query("SELECT * FROM mbr_qa_questions ORDER BY q_votes DESC);
while($row = mysql_fetch_array($qry_questions){
//Grab all information
}
Now, I need to make three queries that act like the one above, but I need it to do something like this:
pull everything from every third row in a table starting at row #1
pull everything from every third row in a table starting at row #2
pull everything from every third row in a table starting at row #3
Then I would put each of those queries into one of the 3 columns.
I can not do this by unique ID. Yes, it is an auto incrementing ID, but it will be probable that I might have to move whole rows into another table.
EDIT: I've added my attempt to count each row and place the queried result into the right "bin"
//GIVE EACH ENTRY A COLUMN NUMBER
$count++;
if($count >= 4){
$count = 1;
}?>
<div class="col" id="col-1">
<?PHP
while($count == 1){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
<div class="col" id="col-2">
<?PHP
while($count == 2){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
<div class="col" id="col-3">
<?PHP
while($count == 3){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
Here's one approach, to get the resultset returned by MySQL. (But it might be easier to just return all the rows, and get every third row within the app). But it can be done in MySQL pretty easily. Note that your original query is wrapped in parens (as an inline view) aliased as r.
SELECT r.*
FROM (
SELECT *
FROM mbr_qa_questions
ORDER BY q_votes DESC
) r
CROSS
JOIN ( SELECT #i := 0 ) s
HAVING ( #i := #i + 1) MOD 3 = 1
That will return every third row, starting with the first row. To get every third row starting with the 2nd and 3rd row, replace the literal = 1 in the HAVING clause with = 2 or = 3 (respectively).
Why do you need three different queries? Can you not, instead, keep the single query you have, have a counter that is incremented in every iteration of the loop, and on %3 does whatever you would do for cases #1, #2 or #3?
you can probably just use a counter to do it in a much simpler fashion, but I would do it like this:
$questions = array();
$results = mysql_query("SELECT * FROM mbr_qa_questions ORDER BY q_votes DESC");
while($row = mysql_fetch_array($results)){
$questions[] = $row;
}
for($i = 0; $i < count($questions); $i++) {
if($i + 1 % 3 == 0) {
$questions[$i];//this is a 3rd, so do something with it
}
}
Related
I want to find the position of a row when I order the table in a descending order. I used the following to order the rows in a descending order.
SELECT * FROM feature Order BY Votes DESC
I need to find what position the row is in compared to others, such as 1st, 5th, 8th...
I was thinking of using a loop that loops through each value in the ordered from greatest to lowest and if the votes are greater than the previous value but more than the next value, then the position can be found. However, I found this to be impractical if there are many rows in the table. How can I find the relative standing of a row? A simple direction will be sufficient.
If I understand correctly, you could loop through the result as an assoc array, with an $i variable increased each iteration. That $i variable would tell you each row's position in order.
$query = "SELECT * FROM feature Order BY Votes DESC";
$result = mysqli_query($connect, $query);
$i = 1;
while ($row = mysqli_fetch_assoc($result)) {
$id = $row['idColumnName'];
if ($id == 'idNumber'){
echo("My ID is: ".$id." and I am voted number: ".$i);
}
$i++;
}
I'm trying to do a next and previous button based on records from database but i'm not really sure how to do it and which would be the best way.
The way that i was thinking to do it
would be to have a field in the table named position.
and the query would look like this:
SELECT * FROM t1 WHERE step = 1
then in the php i would have something like this
$step = $step + 1 // for the next button
if($step === 1) {
$step = 1;
} else {
$step = $step - 1;
}
But if i would delete a record then my position would be out of sync with the math and i won't be able to do + or - on step field because i would find the record.
Which means everytime i would delete something i would need to do a new increment on that field to keep it synced which might later become a problem.
How should i handle it ?
You can add a row number to a query like this:
select #qposn:=#qposn+1 posn, a.* from sometable a, (select #qposn:=0) x
You can select a specific row, in this case the 2nd row, like this:
select * from (
select #qposn:=#qposn+1 posn, a.* from sometable a, (select #qposn:=0) x
) x where posn=2
But be aware that if the data in the table changes the numbering will change also. If someone deletes the first record in the table then the data that used to be row 2 will now be row 1 and so paging may skip or repeat rows.
If your table is relatively small you might consider caching the table in a javascript array and then paging through the array.
I am just a student at php, I am trying to find out a list of members from a table where I dont know how much rows are in that table, but I need every 6 rows on Order By entrytime DESC basis.
My table structure is as below:
int `ID`
int `entrytime` // this time updates when rows insert
now I need to find out all ids on basis of entrytime DESC and insert those ids in a separate new table say "new_tbl" as a group of 6 ids
ind `ID`
varchar `group_name`
I am trying to do like this :
$qry=mysql_query("SELECT id FROM main_table entrytime ASC");
while($res=mysql_fetch_row($qry)){
$id=$res['0'];
$q=mysql_query();
######### But not getting any Idea how to find every 6 Ids and insert in new_tbl #######
}
In your case you use mysql_fetch_row this gives you the count of rows and not the data.
while($res=mysql_fetch_assoc($qry)) {
To get the Data you have to use mysql_fetch_assoc for example.
To find every 6 Ids you can make a counter and increment the value by 1. If the modulo of 6 and the value is 0 you have the sixth value and you can reset the counter.
$i = 1;
while ...
if($i % 6 == 0) {
// reset your counter
$i = 1;
}
$i++;
}
Then you can use the counter to work with it and write that to another table for example.
I have the following table:
id | name | position
1 Bob 4
2 Jim 5
3 Harry 73
4 Paul 89
I want the user to be able to re-order the columns as they see fit, like move one row up and down, using the position column. I have thrown in the big numbers in there (73 and 89) just to cater for all events.
Is there a way to dynamically re-order the table via SQL? Or will I have to manually re-order all tables when someone selects 'move up' on 'Harry'? I can only imagine I will have to:
Find the ID before Harry's (in this case '2')
Move all ID's (including '2's) up by one.
Set Harry's position to to '2'.
There must be a quicker easier way to do this using MySQL/PHP?
If can you provide position order after pressing each up or down you can use following query. That is if current position is 4,5,73,89, suppose user selected 89 and pressed up. In that case if you can provide 4,5,89,73 to query then following query will help you
select * from table22 order by field(position,4,5,89,73);
you just need to use a simple case in your update statement, see example below for moving a number up. For moving a numberdown, same case with minor adjustment, and you can use a nested case to decide which to use by comparing number and destination
set #nr=4; set #dest=2;
select *,
case
when number between #dest and #nr-1 then number+1
when number=#nr then #dest
else number
end as number_alt
from
(
select 1 as number union select 2 union select 3 union select 4 union select 5
)a
For those that find this page in the future, I found some code from an old shop that did the trick:
if((isset($_POST['moveup_x'])) || (isset($_POST['movedown_x']))) {
$current = select("SELECT `position` FROM `events` WHERE `id`='".rEsc($eventid)."';", true,true);
if(isset($_POST['moveup_x'])) $target = ($current - 1);
if(isset($_POST['movedown_x'])) $target = ($current + 1);
if($current > 1) {
$counter = 1;
foreach(select("SELECT `id` FROM `events` ORDER BY `position`;") as $val)
{
$newposition = $counter;
if($current == $newposition) {
$newposition = $target;
} elseif(($current > $newposition) && ($target <= $newposition)) {
$newposition++;
} elseif(($current < $newposition) && ($target >= $newposition)) {
$newposition--;
}
runSQL("UPDATE `events` SET `position`='{$newposition}' WHERE `id`='{$val['id']}';");
$counter++;
}
array_push($msgs,"Successfully moved event.");
} else {
array_push($msgs,"!Cannot move the event any higher up the list.");
}
}
You need to know your current, which you can get from $_POST (in this case I got from rowID in the database) and your target (I had img submit buttons so I just minused or plussed from whichever button the user clicks). Once you have that, loop through each row in the table however you see fit, (set a counter beforehand) and run the IF/ELSE statement. Modify for your need.
It works very well though. There problably is a quicker/easier way, i.e. all in one SQL statement, instead of updating every single row in the database, but I couldnt find it.
I have a table with roughly 1 million rows. I'm doing a simple program that prints out one field from each row. However, when I started using mysql_pconnect and mysql_query the query would take a long time, I am assuming the query needs to finish before I can print out even the first row. Is there a way to process the data a bit at a time?
--Edited--
I am not looking to retrieve a small set of the data, I'm looking for a way to process the data a chunk at a time (say fetch 10 rows, print 10 rows, fetch 10 rows, print 10 rows etc etc) rather than wait for the query to retrieve 1 million rows (who knows how long) and then start the printing.
Printing one million fields will take some time. Retrieving one million records will take some time. Time adds up.
Have you profiled your code? I'm not sure using limit would make such a drastic difference in this case.
Doing something like this
while ($row = mysql_fetch_object($res)) {
echo $row->field."\n";
}
outputs one record at a time. It does not wait for the whole resultset to be returned.
If you are dealing with a browser you will need something more.
Such as this
ob_start();
$i = 0;
while ($row = mysql_fetch_object($res)) {
echo $row->field."\n";
if (($i++ % 1000) == 0) {
ob_flush();
}
}
ob_end_flush();
Do you really want to print one million fields?
The customary solution is to use some kind of output pagination in your web application, showing only part of the result. On SELECT queries you can use the LIMIT keyword to return only part of the data. This is basic SQL stuff, really. Example:
SELECT * FROM table WHERE (some conditions) LIMIT 40,20
shows 20 entries, starting from the 40th (off by one mistakes on my part may be possible).
It may be necessary to use ORDER BY along with LIMIT to prevent the ordering from randomly changing under your feet between requests.
This is commonly needed for pagination. You can use the limit keyword in your select query. Search for limit here:
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
With one argument, the value specifies the number of rows to return from the beginning of the result set:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
In other words, LIMIT row_count is equivalent to LIMIT 0, row_count.
You might be able to use
Mysqli::use_result
combined with a flush to output the data set to the browser. I know flush can be used to output data to the browser at an incremental state as I have used it before to do just that, however I am not sure if mysqli::use_result is the correct function to retrieve incomplete result sets.
This is how I do something like that in Oracle. I'm not sure how it would cross over:
declare
my_counter integer := 0;
begin
for cur in (
select id from table
) loop
begin
-- do whatever your trying to do
update table set name = 'steve' where id = cur.id;
my_counter := my_counter + 1;
if my_counter > 500 then
my_counter := 0;
commit;
end if;
end;
end loop;
commit;
end;
An example using the basic mysql driver.
define( 'CHUNK_SIZE', 500 );
$result = mysql_query( 'select count(*) as num from `table`' );
$row = mysql_fetch_assoc( $result );
$totalRecords = (int)$row['num'];
$offsets = ceil( $totalRecords / CHUNK_SIZE );
for ( $i = 0; $i < $offsets; $i++ )
{
$result = mysql_query( "select * from `table` limit " . CHUNK_SIZE . " offset " . ( $i * CHUNK_SIZE ) );
while ( $row = mysql_fetch_assoc( $result ) )
{
// your per-row operations here
}
unset( $result, $row );
}
This will iterate over your entire row volume, but do so only 500 rows at a time to keep memory usage down.
It sounds like you're hitting the limits of various buffer sizes within the mysql server... Some methods you could do would be to specify the field you want in the SQL statement to reduce this buffer size, or play around with the various admin settings.
OR, you can use a pagination like method but have it output all on one page...
(pseudocode)
function q($part) {
$off = $part*SIZE_OF_PARTITIONS;
$size = SIZE_OF_PARTITIONS;
return( execute_and_return_sql('SELECT `field` FROM `table` LIMIT $off, $size'));
}
$ii = 0;
while ($elements = q($ii)) {
print_fields($elements);
$ii++;
}
Use mysql_unbuffered_query() or if using PDO make sure PDO::MYSQL_ATTR_USE_BUFFERED_QUERY is false.
Also see this similar question.
Edit: and as others have said, you may wish to combine this with flushing your output buffer after each batch of processing, depending on your circumstances.