Referencing the next iteration before it happens in PHP - php

I have a table in MySQL with "text", "date_posted", and "user". I currently query all text from user=Andy, and call those questions. All of the other text fields from other users are answers to the most recent question.
What I want is to associate those answers with the most recent question, with a loop similar to "for each text where user=Andy, find the text where user!=Andy until date>the next user=Andy (question)"
This seems awfully contrived, and I'm wondering if it can be done roughly as I've outlined, or if I can save myself some trouble in how I'm storing the data or something.
Thanks for any advice.
EDIT: I've added in the insert queries I've been using.
$url = "http://search.twitter.com/search.json?q=&ands=&phrase=&ors=&nots=RT%2C+%40&tag=andyasks&lang=all&from=amcafee&to=&ref=&near=&within=1000&units=mi&since=&until=&tude%5B%5D=%3F&rpp=50)";
$contents = file_get_contents($url);
$decode = json_decode($contents, true);
foreach($decode['results'] as $current) {
$query = "INSERT IGNORE INTO andyasks (questions, date, user) VALUES ('$current[text]','$current[created_at]','Andy')";
mysql_query($query);
}
$url2 = "http://search.twitter.com/search.json?q=&ands=&phrase=&ors=&nots=RT&tag=andyasks&lang=all&from=&to=amcafee&ref=&near=&within=15&units=mi&since=&until=&rpp=50";
$contents2 = file_get_contents($url2);
$decode2 = json_decode($contents2, true);
foreach($decode2['results'] as $current2) {
$query2 = "INSERT IGNORE INTO andyasks (questions, date, user) VALUES ('$current2[text]','$current2[created_at]','$current2[from_user]')";
mysql_query($query2);
}
And then on the SELECT side, this is where I am currently:
$results = mysql_query("SELECT * FROM andyasks");
$answers = mysql_query("SELECT * FROM andyasks WHERE 'user' != 'Andy'");
while($row = mysql_fetch_array($results))
{
if ($row['user'] == 'Andy') {
print(preg_replace($pattern, $replace, "<p>".$row["questions"]."</p>"));
}
}
while($row = mysql_fetch_array($answers))
{
print(preg_replace('/#amcafee/', '', "<p>".$row["questions"]."</p>"));
}

What you have in mind could, I believe, be done with subtle use of JOIN or nested SELECT, ORDER BY, LIMIT, etc, but, as you surmise, it would be "awfully contrived" and likely pretty slow.
As you suspect, you would save yourself a lot of trouble at SELECT time if you added a column to the table, which, for answers, has the primary key of the question they're answering (that could be easily obtained at INSERT time, since it's the latest entry with user equal Alex). Then the retrieval would be easier!
If you can alter your schema this way, but need help with the SQL, pls comment or edit your answer to indicate that and I'll be happy to follow up (similarly, I'd be happy to follow up if you're stuck with this schema and need the "awfully contrived" SQL -- I just don't know which of the two possibilities applies!-).
Edit: since the schema's changed, the INSERT could be (using form :name to indicate parameters you should bind):
INSERT IGNORE INTO andyasks
(questions, date, user, answering)
SELECT :text, :created_at, :from_user,
IF(:from_user='Andy', NULL, aa.id)
FROM andyasks AS aa
WHERE user='Andy'
ORDER BY date DESC
LIMIT 1
i.e.: use INSERT INTO ... SELECT' to do a query-within-insertion, which picks the latest post by Andy. I'm assuming you do also have a primary keyid` that's auto-increment, which is the normal arrangement of things.
Later to get all answers to a given question, you only need to select rows whose answering attribute equals that question's id.

If I understand you correctly you want something like:
$myArr = array("bob","joe","jennifer","mary");
while ($something = next($myArr)) {
if ($nextone = next($myArr)) {
//do Something
prev($myArr)
}
}
see http://jp2.php.net/next as well as the sections on prev, reset and current

Related

updatepricing in MySQL where multiple prices are in same row

I have been tasked to update the price list on our website. Currently, we have to do this one item at a time inside the Admin Panel.
However, we have over 3000 items, and tiered pricing for each item (up to 5 tiers)
Problem is, in the sell_prices table, the prices are structured like so:
10.50:9.50:8.50;7.50;6.50 in one cell.
I am attempting to write a script that will update each sell_price by 10%
UPDATE inv_items
SET sell_prices = sell_prices * 1.10
WHERE id = xxxxxx
I have also tried:
UPDATE inv_items
SET sell_prices = sell_prices * 1.10; sell_prices = sell_prices * 1.10
WHERE id = xxxxxx
But naturally received an error.
This works great but only updates one record, and leaves the rest blank.
Currently, I am working through PhpMyAdmin but I will write a new Price Increase script once I can figure this out.
I have backed up the database.
If I understand you correctly then you have 5? prices in one field, colon separated?
That is a really bizarre way of doing it. There may be a nifty way of doing it with mySQL parsing, but from PHP you're going to need to pull the values out, explode them into an array, apply the price increase to each element, implode it back with the colons and write it back to the database. It's as clunky as all get-out but faster than doing it by hand. Just.
Going forward if you can you really need to look at refactoring that; that's just going to keep biting you.
You'll need to do something like:
select sell_prices from inv_items
(get the values into php)
(split the values by delimiter ':')
(update each value)
(rebuild the line of values with ':' in between)
update inv_items set sell_prices = (value string you just created)
EDIT with mysqli function as suggested:
$qry = 'SELECT id, sell_prices FROM `tablename`';
if($result = $mysqli->query($qry)) {
while ($row = $result->fetch_assoc()) {
$temp = explode(';', $row['sell_prices']);
foreach ($temp as &$price) {
$price = (float)$price*1.1;
}
$prices[$row['id']] = implode(';', $temp);
}
foreach ($prices as $id => $pricesStr) {
$stmt = $mysqli->prepare("UPDATE `tablename` SET sell_prices = ? WHERE id = ?");
$stmt->bind_param('si', $pricesStr, $id);
$stmt->execute();
$stmt->close();
}
}
Please note that I wrote this on the fly without testing, i may overlooked something :)

mysql data insert in php

let me explain my problem..actualy i have a table where patient report get stored and patient can have more than one test so the result for every report should be different on print, result is inserting differnt but the field remark and nor inserting same value for more than one test..
this is input field image of report
and the field row can increase acording to increase of tested by patient..
now i am using this for inserting in table
function save_report_content()
{
$R=DIN_ALL($_REQUEST);
$dt = time();
foreach($R as $k=>$v)
{
$test_id = str_replace('rep_result_', '', $k);
if(strstr($k, 'rep_result_'))
{
$content = $v;
$SQL = "INSERT INTO report SET
rep_te_id = '$test_id',
rep_result = '$content',
record_id = '$R[payment_id]',
remark= '$R[remark]',
nor= '$R[nor]',
rep_date = '$dt'";
now result is going differently in table but remark and nor same for more than one test
i spend so much time to recover this problem but did not succeed, if i miss any relevant info regarding this question then feel free to ask me, and thanks in advance, any idea will be appreciate highly....
Whats the structure of your form ?
<input name='nor[]' />
It should be an array to allow each rows value to come other wise just the last rows value will come ...
when you are in the foreach .. you shouldn't use $R[remark] since you are using $k=>$v
it should be $v['remark']

text input (seperated by comma) mysql input as array

I have a form where I am trying to implement a tag system.
It is just an:
<input type="text"/>
with values separated by commas.
e.g. "John,Mary,Ben,Steven,George"
(The list can be as long as the user wants it to be.)
I want to take that list and insert it into my database as an array (where users can add more tags later if they want). I suppose it doesn't have to be an array, that is just what seems will work best.
So, my question is how to take that list, turn it into an array, echo the array (values separated by commas), add more values later, and make the array searchable for other users. I know this question seems elementary, but no matter how much reading I do, I just can't seem to wrap my brain around how it all works. Once I think I have it figured out, something goes wrong. A simple example would be really appreciated. Thanks!
Here's what I got so far:
$DBCONNECT
$artisttags = $info['artisttags'];
$full_name = $info['full_name'];
$tel = $info['tel'];
$mainint = $info['maininst'];
if(isset($_POST['submit'])) {
$tags = $_POST['tags'];
if($artisttags == NULL) {
$artisttagsarray = array($full_name, $tel, $maininst);
array_push($artisttagsarray,$tags);
mysql_query("UPDATE users SET artisttags='$artisttagsarray' WHERE id='$id'");
print_r($artisttagsarray); //to see if I did it right
die();
} else {
array_push($artisttags,$tags);
mysql_query("UPDATE users SET artisttags='$artisttags' WHERE id='$id'");
echo $tags;
echo " <br/>";
echo $artisttags;
die();
}
}
Create a new table, let's call it "tags":
tags
- userid
- artisttag
Each user may have multiple rows in this table (with one different tag on each row). When querying you use a JOIN operation to combine the two tables. For example:
SELECT username, artisttag
FROM users, tags
WHERE users.userid = tags.userid
AND users.userid = 4711
This will give you all information about the user with id 4711.
Relational database systems are built for this type of work so it will not waste space and performance. In fact, this is the optimal way of doing it if you want to be able to search the tags.

Query for select multiple values from 2 tables

Table names:
tbla_can_types
Fields are fac_id,type_id,type_name,status
tbla_canteen_rates (there is no data in this table)
Fields are `fac_id,cat_id,type_id,from time,to_time,rate,off_rate,status,effective_date.,can_id(sequence number)
<?php
include('adodb/adodb.inc.php');
$conn=&ADONewconnection('oci8');
$conn->Pconnect('conn','hostname','username','pwd');
$fac_id=$_GET['fac_id'];
$cat_id=$_GET['cat_id'];
$file=fopen("text.txt","w+");
global $newId;
header("Content-type: text/xml");
echo('<?xml version="1.0" encoding="iso-8859-1"?>');
echo "<data>";
$ids = explode(",",$_POST["ids"]);
$rates="select type_id,from_time,to_time,rate,off_rate,status,to_char(effective_date,'dd-Mon-yyyy') e_date,can_id from tbla_canteen_rates where fac_id=$fac_id and cat_id=$cat_id order by to_number(substr(from_time,0,length(from_time)-3))";
$rs1=$conn->Execute($rates);
if(!$rs1->EOF)
echo $rs1->fields[0].'~'.$rs1->fields[1].'~'.$rs1->fields[2].'~'.$rs1->fields[3].'~'.$rs1->fields[4].'~'.$rs1->fields[5].'~'.$rs1->fields[6].'~'.$rs1->fields[7];
$temp_id=$rs1->fields[0];
echo $temp_id;
$rs1->MoveNext();
for ($i=0; $i < sizeof($ids); $i++)
{
$rowId = $ids[$i]; //id or row which was updated
$newId = $rowId; //will be used for insert operation
$mode = $_POST[$rowId."_!nativeeditor_status"]; //get request mode
switch($mode)
{
case "inserted":
$insert= "insert into tbla_canteen_rates(type_id,from_time,to_time,rate,off_rate,status,effective_date,fac_id,cat_id )values
($temp_id,
'".$_POST[$rowId."_c1"]."',
'".$_POST[$rowId."_c2"]."',
'".$_POST[$rowId."_c3"]."',
'".$_POST[$rowId."_c4"]."',
'".$_POST[$rowId."_c5"]."',to_date('".$_POST[$rowId."_c6"]."','dd-Mon-yyyy'),$fac_id,$cat_id)";
$conn->Execute($insert);
fwrite($file,$insert);
$action='add_row($rowId)';
break;
case "deleted":
$delete = "delete from tbla_canteen_rates where can_id=".$rowId ;
$conn->Execute($delete);
fwrite($file,$delete);
$action ='delete_row($rowId)';
break;
default:
$update ="update tbla_canteen_rates set
type_id=$temp_id,
from_time='".$_POST[$rowId."_c1"]."',
to_time='".$_POST[$rowId."_c2"]."',
rate='".$_POST[$rowId."_c3"]."',
off_rate='".$_POST[$rowId."_c4"]."',
status='".$_POST[$rowId."_c5"]."',
effective_date=to_date('".$_POST[$rowId."_c6"]."','dd-Mon-yyyy'),
fac_id='$fac_id',cat_id='$cat_id'
where can_id=".$rowId;
$conn->Execute($update);
fwrite($file,$update);
$action = 'update_row($rowId)';
break;
}
echo "<action type='".$action."' sid='".$rowId."' tid='".$newId."'/>";
}
echo "</data>";
?>
In the query i need id for type_id in a variable
i have written but every time it is getting id of first element only.
in this i need an id for type_id.
please send me the code 4 that
Regards
Pawan
I've got a sneaking suspicion that you've got several questions in there, but since you asked about the sql query, this should work:
Note: I'm assuming fac_id is the id that binds the two tables together. "var_fac_id" and "var_cat_id" are the values from your comboboxes.
Select t1.type_name, t2.from_time, t2.to_time, t2.rate
FROM tbla_can_types as t1 LEFT JOIN tbla_canteen_rates as t2
ON t1.fac_id = t2.fac_id
WHERE t1.fac_id = var_fac_id AND t2.cat_id = var_cat_id
Further notes: I think this should work despite the "AND t2.cat_id = var_cat_id" (which obviously would find not results in an empty table), since it's a left join. If it returns an empty set, however, see if it works if you remove it.
Update:
your comment above makes me think the tables are bound together by type_id instead. If that's the case, use ON t1.type_id = t2.type_id instead of ON t1.fac_id = t2.fac_id
Update #2 based on poster's comments
I'm not going to do your homework, dude. And homework is the only place where they'd tell you to not do joins. I will send you to some resources that will help you learn this stuff, though. Check out the basic mysql example from php.net: http://www.php.net/manual/en/mysql.examples-basic.php . That sample actually gets you pretty close to what you need. Also their overall mysql documentation, which is good for looking up what specific functions do: http://www.php.net/manual/en/book.mysql.php . Finally, remember that you're learning two languages here -- PHP, along with its functions to access a mysql DB, and -- SQL, which is a query language used within DBs. For SQL, check out http://sqlzoo.net/ , which seems a decent introduction on how to write queries.
Good luck on your assignment.

how to identify the source table of fields from a mysql query

I have two dynamic tables (tabx and taby) which are created and maintained through a php interface where columns can be added, deleted, renamed etc.
I want to read all columns simulataneously from the two tables like so;-
select * from tabx,taby where ... ;
I want to be able to tell from the result of the query whether each column came from either tabx or taby - is there a way to force mysql to return fully qualified column names e.g. tabx.col1, tabx.col2, taby.coln etc?
In PHP, you can get the field information from the result, like so (stolen from a project I wrote long ago):
/*
Similar to mysql_fetch_assoc(), this function returns an associative array
given a mysql resource, but prepends the table name (or table alias, if
used in the query) to the column name, effectively namespacing the column
names and allowing SELECTS for column names that would otherwise have collided
when building a row's associative array.
*/
function mysql_fetch_assoc_with_table_names($resource) {
// get a numerically indexed row, which includes all fields, even if their names collide
$row = mysql_fetch_row($resource);
if( ! $row)
return $row;
$result = array();
$size = count($row);
for($i = 0; $i < $size; $i++) {
// now fetch the field information
$info = mysql_fetch_field($resource, $i);
$table = $info->table;
$name = $info->name;
// and make an associative array, where the key is $table.$name
$result["$table.$name"] = $row[$i]; // e.g. $result["user.name"] = "Joe Schmoe";
}
return $result;
}
Then you can use it like this:
$resource = mysql_query("SELECT * FROM user JOIN question USING (user_id)");
while($row = mysql_fetch_assoc_with_table_names($resource)) {
echo $row['question.title'] . ' Asked by ' . $row['user.name'] . "\n";
}
So to answer your question directly, the table name data is always sent by MySQL -- It's up to the client to tell you where each column came from. If you really want MySQL to return each column name unambiguously, you will need to modify your queries to do the aliasing explicitly, like #Shabbyrobe suggested.
select * from tabx tx, taby ty where ... ;
Does:
SELECT tabx.*, taby.* FROM tabx, taby WHERE ...
work?
I'm left wondering what you are trying to accomplish. First of all, adding and removing columns from a table is a strange practice; it implies that the schema of your data is changing at run-time.
Furthermore, to query from the two tables at the same time, there should be some kind of relationship between them. Rows in one table should be correlated in some way with rows of the other table. If this is not the case, you're better off doing two separate SELECT queries.
The answer to your question has already been given: SELECT tablename.* to retrieve all the columns from the given table. This may or may not work correctly if there are columns with the same name in both tables; you should look that up in the documentation.
Could you give us more information on the problem you're trying to solve? I think there's a good chance you're going about this the wrong way.
Leaving aside any questions about why you might want to do this, and why you would want to do a cross join here at all, here's the best way I can come up with off the top of my head.
You could try doing an EXPLAIN on each table and build the select statement programatically from the result. Here's a poor example of a script which will give you a dynamically generated field list with aliases. This will increase the number of queries you perform though as each table in the dynamically generated query will cause an EXPLAIN query to be fired (although this could be mitigated with caching fairly easily).
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
function aliasFields($pdo, $table, $delim='__') {
$fields = array();
// gotta sanitise the table name - can't do it with prepared statement
$table = preg_replace('/[^A-z0-9_]/', "", $table);
foreach ($pdo->query("EXPLAIN `".$table."`") as $row) {
$fields[] = $table.'.'.$row['Field'].' as '.$table.$delim.$row['Field'];
}
return $fields;
}
$fieldAliases = array_merge(aliasFields($pdo, 'artist'), aliasFields($pdo, 'event'));
$query = 'SELECT '.implode(', ', $fieldAliases).' FROM artist, event';
echo $query;
The result is a query that looks like this, with the table and column name separated by two underscores (or whatever delimeter you like, see the third parameter to aliasFields()):
// ABOVE PROGRAM'S OUTPUT (assuming database exists)
SELECT artist__artist_id, artist__event_id, artist__artist_name, event__event_id, event__event_name FROM artist, event
From there, when you iterate over the results, you can just do an explode on each field name with the same delimeter to get the table name and field name.
John Douthat's answer is much better than the above. It would only be useful if the field metadata was not returned by the database, as PDO threatens may be the case with some drivers.
Here is a simple snippet for how to do what John suggetsted using PDO instead of mysql_*():
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$query = 'SELECT artist.*, eventartist.* FROM artist, eventartist LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch()) {
foreach ($row as $key=>$value) {
if (is_int($key)) {
$meta = $stmt->getColumnMeta($key);
echo $meta['table'].".".$meta['name']."<br />";
}
}
}

Categories