I have a PDO query in which I am doing inner join on two tables and extracting the columns required by me.
Now these two columns are - status, script.
Status can be - passed, failed, incomplete and
script - scripts/testSuite/layer3Features/ManualStaticRouting/manualStaticRoutes.tcl , scripts/testSuite/hostAgentFeatures/dhcp/DHCP IPv6/RelayBBasicFunc/ipv6DhcpRelayEnableDhcpv6RelayGlobally.tcl
the output of --
while($row = $getFamily->fetch(PDO::FETCH_ASSOC))
{
foreach($row as $key)
{
print_r($row);
}
is -
http://pastebin.com/WqcibEyp
the full query is -
$testType = 'TCL';
$getFamily = $conn->prepare('SELECT testcases2.script, results3.status FROM testcases2 INNER JOIN results3 ON testcases2.testcaseID = results3.testcaseID
WHERE testType = :testType');
$getFamily->execute(array(':testType' => $testType));
while($row = $getFamily->fetch(PDO::FETCH_ASSOC))
{
foreach($row as $key)
{
print_r($row);
$family[] = $key;
}
}
Now here what I want to do is, read the second location of each script (considering scripts at 0) and group all the values which have same stuff in the third location, with status together.
How this can be done.
Please guide.
You need to group your script and status like this,
while($row = $getFamily->fetch(PDO::FETCH_ASSOC))
{
$status[] = $row['status'];
$scripts[] = $row['script'];
}
print_r($scripts);
print_r($status);
Related
I have extracted all the domains I have from my database, I would like to draw all comments to the domains that are added in the database.
$results = $mysqli->query("SELECT domain_name, id_view FROM domain GROUP BY domain_name ORDER BY domain_name");
$comment = $mysqli->query("SELECT domain_name, id_view, comment FROM domain_comment");
$id_array = array();
while($row = mysqli_fetch_array($comment)) {
$id_array[] = $row['comment'];
$id_array[] = $row['id_view'];
}
while($row = mysqli_fetch_array($results))
{
$section = $row['id_view'];
foreach ($id_array as $sectionname) {
if ($sectionname == $section) {
echo $sectionname;
}
}
}
The data it receives is VIEW ID and not Comment, what am I doing wrong?
EDIT:
When he gives the Select query:
$comment = $mysqli->query("SELECT comment FROM domain_comment INNER JOIN domain ON domain_comment.id_view = domain.id_view");
while($row = mysqli_fetch_array($results))
{
while($row2 = mysqli_fetch_array($comment))
{
echo $row2['comment'];
}
}
It prints all the comments at the first domain.
The result I have:
The result he wants:
this part
$id_array[] = $row['comment'];
$id_array[] = $row['id_view'];
What are you trying to do?
inserting comment in the id array? in this case the id_array will have one comment and one id, i dont think this is what you want. and second loop definitely us $row2 it is safer and wont mix up. inner join the quickest way.you are already there i think.
try removing the line
$id_array[] = $row['comment'];
and check.
for innerjoin you can try to innerjoin on two keys i.e also domain.
$comment = $mysqli->query("SELECT comment FROM domain_comment INNER JOIN domain ON domain_comment.id_view = domain.id_view and domain_comment.domain_name = domain.domain_name");
while($row = mysqli_fetch_array($comment)) {
$id_array[$row['id_view']]['comments'][] = $row['comment'];
}
while($row = mysqli_fetch_array($results))
{
$id_array[$row['id_view']]['data'] = $row;
}
You can try this solution after just dump $id_array in this case it would be much more easier to handle data.
First time tackling a project where i'm needing to pull data from one table (lets say 200 records/results), and based on the results of a certain column within that result set, i need to query one of my 5 other tables (which table i need to query isnt defined until i've made the first query)
I'm currently under the impression there is no way for me to use a JOIN of some kind to do this as i cannot know which table i need to join before the first set of results have come back.
so the solution i came up with was as follows (example code for simplicity sake)
$FirstTableVals = array();
$sql = ("SELECT * FROM TABLE_A");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
foreach($row as $key => $value)
{
$FirstTableVals[$key] = $value;
}
$valueToSwitch = $FirstTableVals["VAL_TO_SWITCH"];
//$SecondTable can be 1 of 5 different table names
$SecondTable = $FirstTableVals["SECOND_TABLE_TO_QUERY"];
switch ($valueToSwitch)
{
case"1":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_COLUMN = SOME_VALUE");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
case"2":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_OTHER_COLUMN = SOME_OTHER_VALUE");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
default:
break;
}
}
}
Now, the problem i'm running into is that once one of the "Second" sql queries is executed, after performing everything within the "Second" While loop, it will break out of the while loop its in and echo my values but stops there without breaking out of the switch statement and then running again, due to the "First" sql queries loop.
Essentially, this only seems to run for the first record inside of "TABLE_A" as opposed to looping again and executing the switch statement with "Second" sql queries for each record inside of "TABLE_A".
If any of this doesn't make any sense, please let me know and i'll do my best to elaborate on anything that may be confusing.
Really stumped with this one as it seems to me that should run as i've intended.
You are overridding the run variable, thats why it breaks the loop. Please change your code like this:
$FirstTableVals = array();
$sql = ("SELECT * FROM TABLE_A");
$run1 = $con->query($sql);
if($run1->num_rows > 0)
{
while($row = $run1->fetch_assoc())
{
foreach($row as $key => $value)
{
$FirstTableVals[$key] = $value;
}
$valueToSwitch = $FirstTableVals["VAL_TO_SWITCH"];
//$SecondTable can be 1 of 5 different table names
$SecondTable = $FirstTableVals["SECOND_TABLE_TO_QUERY"];
switch ($valueToSwitch)
{
case"1":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_COLUMN = SOME_VALUE");
$run2 = $con->query($sql);
if($run2->num_rows > 0)
{
while($row = $run2->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
case"2":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_OTHER_COLUMN = SOME_OTHER_VALUE");
$run3 = $con->query($sql);
if($run3->num_rows > 0)
{
while($row = $run3->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
default:
break;
}
}
}
I have 10-20 log-tables in a MySQL database. Each table contains 50-100.000 rows. I need to export these to XML and sort them by creation date.
Union is a good option as the tables doesn't contain the same columns (one table might contain 3 column, and another 30 columns).
This is how I create the XML:
// Events
$stmt = $db->query("
SELECT id, columnX, created
FROM table1
");
$row_count = $stmt->rowCount();
if ($row_count != '0') {
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$event = $xml->createElement("event");
$events->appendChild($event);
$event->appendChild($xml->createElement("ID", "XXXX"));
$event->appendChild($xml->createElement("columnX", $row['columnX']));
$event->appendChild($xml->createElement("created", $row['created']));
}
}
// Other events
$stmt = $db->query("
SELECT id, columnY1, columnY2, columnY3, created
FROM table2
");
$row_count = $stmt->rowCount();
if ($row_count != '0') {
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$event = $xml->createElement("event");
$events->appendChild($event);
$event->appendChild($xml->createElement("ID", "XXXX"));
$event->appendChild($xml->createElement("columnY1", $row['columnY1']));
$event->appendChild($xml->createElement("columnY2", $row['columnY2']));
$event->appendChild($xml->createElement("columnY3", $row['columnY3']));
$event->appendChild($xml->createElement("created", $row['created']));
}
}
Anyone got an idea of how to solve this?
I suggest using an INSERT INTO ... SELECT ... UNION ... SELECT construct to fetch all the data into a (temporary) table. INSERT INTO ... SELECT allows you to directly insert the result of an select into a table. UNION allows you to concat SELECT results. Because it is a database statement it all happens in the DBMS.
After that use a select to fetch the data ordered by date field and use XMLWriter to create the XML.
If there is possibility to sort all queries, you are able to sort final XML by getting all queries from database and then printing out them like in code bellow.
Be aware, that this code WILL probably consume as much memory as data returned by all queries in one time, because you cannot use unbuffered query in this case. I don't know, how big are datasets, you are talking about.
If memory would be your concern, you can use same algorithm to combine any data source. So you can prepare three XML files (per query) and combine these instead of combining SQL. It would be (in combination with mysql unbuffered queries) probably better variant for memory usage, but slower as you will need generate and parse XML.
// convert queries to generator
function processQuery(mysqli $db, $sql) {
$q = $db -> query($sql);
while ($row = $q -> fetch_assoc()) {
// just yield
yield $row;
}
}
// prepare all queries
$queries = [
processQuery($db, "SELECT id, columnX, created FROM table1 ORDER BY created"),
processQuery($db, "SELECT id, columnY1, columnY2, columnY3, created FROM table2 ORDER BY created"),
processQuery($db, "SELECT id, created FROM table3 ORDER BY created"),
];
// run all queries and fetch first row
foreach ($queries as $query) {
$query -> next(); // see \Generator
}
// now, we will run while any query has rows (generator returns key)
while (array_filter(array_map(function(Generator $query) { return $query -> key(); }, $queries))) {
// now we have to find query, which next row has minimal date
$minTimestamp = NULL;
$queryWithMin = NULL;
foreach ($queries as $queryId => $query) {
$current = $query -> current();
if ($current !== FALSE) {
if ($minTimestamp === NULL || $minTimestamp > $current['created']) {
// this query has row with lower date than previous queries
$minTimestamp = $current['created'];
$queryWithMin = $queryId;
}
}
}
// we now know, which query returns row with minimal date
PRINT_TO_XML($queries[$queryWithMin] -> current());
// move cursor of this query to next row
$queries[$queryWithMin] -> next();
}
Another aproach could be MySQL UNION only for getting ids (already sorted) and then process them in batches.
$q = $db -> query("SELECT 'table1' AS tableName, id, created FROM table1
UNION ALL SELECT 'table2' AS tableName, id, created FROM table2
UNION ALL SELECT 'table3' AS tableName, id, created FROM table3
ORDER BY created");
$sorter = [];
while ($row = $q -> fetch_assoc()) {
$sorter []= [$row['tableName'], $row['id']];
}
foreach (array_chunk($sorter, 5000) as $dataChunk) {
// get ids from each table
$table1Ids = array_map(function($rowInfo) { return $rowInfo[1]; }, array_filter($dataChunk, function($rowInfo) { return $rowInfo[0] === 'table1'; }));
$table2Ids = array_map(function($rowInfo) { return $rowInfo[1]; }, array_filter($dataChunk, function($rowInfo) { return $rowInfo[0] === 'table2'; }));
$table3Ids = array_map(function($rowInfo) { return $rowInfo[1]; }, array_filter($dataChunk, function($rowInfo) { return $rowInfo[0] === 'table3'; }));
// load full data from each table
$dataTable1 = [];
$q = $db -> query("SELECT * FROM table1 WHERE id IN (".implode(",", $table1Ids).")");
while ($row = $q -> fetch_assoc()) {
$dataTable1[$row['id']] = CREATE_XML($row);
}
// ... same with table2
// ... same with table3
// store
foreach ($dataChunk as $row) {
if ($row[0] === 'table1') {
echo $dataTable1[$row[1]];
}
if ($row[1] === 'table1') {
echo $dataTable2[$row[1]];
}
if ($row[2] === 'table1') {
echo $dataTable3[$row[1]];
}
}
}
This approach is less memory consuming, but in this exact code, you will need to load all IDs to memory first. It's possible to simple rewrite to generate XML in first loop (if count($sorter) > 5000 { printXmlForIds($sorter); $sorter = []; }) and algorithm would not exceed memory limt.
I have these recordsets an I'm faking a $_POST in between the queries to use a values from the first query to get values from the second query, in this manner I get the first row of many, I've tried a foreach loop in-between the queries and fail...
How do I loop through the first recorset rows as many are returned?.... the code is:
$maxRows_rs_all_classes = 50;
$pageNum_rs_all_classes = 0;
if (isset($_GET['pageNum_rs_all_classes'])) {
$pageNum_rs_all_classes = $_GET['pageNum_rs_all_classes'];
}
$startRow_rs_all_classes = $pageNum_rs_all_classes * $maxRows_rs_all_classes;
mysql_select_db($database_conn_studiogear_mgr, $conn_studiogear_mgr);
$query_rs_all_classes = "SELECT sg_class_desc.class_image,
sg_class_desc.class_location,
sg_classes.class_name,
sg_class_desc.class_room,
sg_classes.class_cat1,
sg_classes.class_cat2,
sg_classes.class_cat3,
sg_classes.class_id
FROM sg_class_desc
INNER JOIN sg_classes
ON sg_class_desc.class_id = sg_classes.class_id";
$query_limit_rs_all_classes = sprintf("%s LIMIT %d, %d",
$query_rs_all_classes,
$startRow_rs_all_classes,
$maxRows_rs_all_classes);
$rs_all_classes = mysql_query($query_limit_rs_all_classes, $conn_studiogear_mgr)
or die (mysql_error());
$row_rs_all_classes = mysql_fetch_assoc($rs_all_classes);
if (isset($_GET['totalRows_rs_all_classes'])) {
$totalRows_rs_all_classes = $_GET['totalRows_rs_all_classes'];
} else {
$all_rs_all_classes = mysql_query($query_rs_all_classes, $conn_studiogear_mgr);
$totalRows_rs_all_classes = mysql_num_rows($all_rs_all_classes);
}
$totalPages_rs_all_classes = ceil($totalRows_rs_all_classes/$maxRows_rs_all_classes)-1;
$_POST['class_id'] = $row_rs_all_classes['class_id'];
//without the following loop I return the first row and the second query works for the first row
// start loop when I use this loop, "Array" is echoed out and next query does not run
$classes = $row_rs_all_classes['class_id']; // from recordset above
foreach ($classes as $value) {
$ArrayClasses[] = "".$value ."";
echo $ArrayClasses; //
}
// end loop
$colname_rs_gear = "-1";
if (isset($_POST['class_id'])) {
$colname_rs_gear = $_POST['class_id'];
}
mysql_select_db($database_conn_prestashop, $conn_prestashop);
$query_rs_gear = sprintf("SELECT ps_product_lang.name,
ps_product.id_product,
ps_product.price,
ps_product.reference,
ps_product_lang.description_short,
ps_product_lang.description,
ps_supplier.name,
sg_class_gear.class_gear_image,
sg_class_gear.class_gear_product_link
FROM ps_product
INNER JOIN ps_product_lang
ON ps_product.id_product = ps_product_lang.id_product
INNER JOIN ps_supplier
ON ps_product.id_supplier = ps_supplier.id_supplier
INNER JOIN sg_class_gear
ON sg_class_gear.class_gear_pid = ps_product.id_product
WHERE ps_product.id_product = sg_class_gear.class_gear_pid
AND sg_class_gear.class_id = %s",
GetSQLValueString($colname_rs_gear, "int"));
$rs_gear = mysql_query($query_rs_gear, $conn_prestashop) or die(mysql_error());
$row_rs_gear = mysql_fetch_assoc($rs_gear);
$totalRows_rs_gear = mysql_num_rows($rs_gear);
1) You are vulnerable to sql injection attacks
2) You are using an obsolete database library (mysql) and should switch to mysqli or PDO
3) mysql_fetch_*() functions return a SINGLE row of data from the result set. Since you're not calling mysql_fetch_in a loop for your initial query, you only ever get the first row of results. Your code should be
$result = mysql_query($first_query_sql);
while($row = mysql_fetch_assoc($result)) {
$result2 = mysql_query($inner_query_sql);
while($row2 = ...) {
}
}
I have switched over to the mysqli_ extension for PHP, and I have ran into a bit of an issue.
I have 2 databases. 1 database I am only allowed read privileges, the other I have all privileges. My end goal is to read what I need from database 1, and put it in a table in database 2.
I use a join on database 1 to get all the information I need. I then loop through the results with a while loop. I have a unique id (domainid) in both databases. Where I am encountering the issue is inside the while loop once I have the domainid from the read-only database, I need to check if it exists inside my all-privileges database. I am just unsure of how to accomplish this?
Here is the code:
require 'db/connect.php';
require 'db/connect2.php';
if($result = $db->query("
SELECT tblhosting.domain as domain, tblhosting.id as domainid, tblclients.email as email
FROM tblhosting
LEFT JOIN tblclients ON
tblclients.id = tblhosting.userid
")){
if ($count = $result->num_rows) {
while($row = $result->fetch_object()){
$domainid = $row->domainid;
$domain = $row->domain;
$email = $row->email;
$result2 = $db2->prepare("SELECT domainid FROM information WHERE domainid = ?");
$result2->bind_param('i', $row->domainid);
$result2->execute();
$result2->bind_result($domainid2);
//$result2->fetch();
while($row2 = $result2->fetch_object()){
$domainid2 = $row2->domainid;
if ($domainid == $domainid2) {
echo "Information exists in both Databases", '<br>';
}
else{
echo "New Information Added to Database 2", '<br>';
}
}
}
}
}
This is what I have tried, but was unsuccessful.
EDIT
Second attempt putting the results into an array then looping through them. The array is correct when I print them out. The issue is with the 2nd execute(); command.
$result = $db->query("
SELECT tblhosting.domain as domain, tblhosting.id as domainid, tblclients.email as email
FROM tblhosting
LEFT JOIN tblclients ON
tblclients.id = tblhosting.userid
");
$domainid_arr = array();
while($row = $result->fetch_object()){
$domainid_arr[] = array(
'domainid' => $row->domainid,
'domain' => $row->domain
);
}
foreach ($domainid_arr as $d) {
echo $d['domainid'], $d['domain'], '<br>';
$result2 = $db2->prepare("SELECT domainid FROM information WHERE domainid = ?");
$result2->bind_param('i', $d['domainid']);
$result2->execute();
$result2->bind_result($domainid2);
while($row2 = $result2->fetch_object()){
$domainid2 = $row2->domainid;
if ($d['domainid'] == $domainid2) {
echo "Information exists in both Databases", '<br>';
}
else{
echo "New Information Added to Database 2", '<br>';
}
}
}