I have three MySQL tables that I need to query for all of the rows. Upon getting all of the rows from each table, I need to create a multidimensional array whereby each index of that array contains only value from each of the tables. What I have right now works. But, something is telling me that there has got to be a better way of accomplishing this.
$tables = array('table_one', 'table_two', 'table_three');
$final = array();
foreach($tables as $table) {
$sql = "SELECT * FROM ".$table."";
$query = mysqli_query($con, $sql)or die(mysqli_error($con));
$num = mysqli_num_rows($query);
$i = 0;
while($row = mysql_fetch_array($query)) {
$id[$i] = $row['user_id'];
$i++;
}
for($i=0;$i<$num;$i++) {
if(!is_array($final[$i])) {
$final[$i] = array($id[$i]);
} else {
array_push($final[$i], $id[$i]);
}
}
}
The end results is something that looks like this
$final = array(array('table_one_row_one_val', 'table_two_row_one_val', 'table_three_row_one_val'),
array('table_one_row_two_val', 'table_two_row_two_val', 'table_three_row_two_val'),
array('table_one_row_three_val', 'table_two_row_three_val', 'table_three_row_three_val')
);
I get the gut felling that this could be done much more effectively, but I'm not sure how.
Thanks,
Lance
You can make your code simpler if you make your query more explicit in selecting the columns you want in the order you want them. So for example:
$sql = 'SELECT table_one.user_id as u1, table_two.user_id as u2, table_three.user_id as u3 FROM ' . implode(',', $tables);
Then each row of your result set will have the columns in the proper order making the construction of your arrays less involved. For example:
$query = mysqli_query($con, $sql)or die(mysqli_error($con));
while($row = mysql_fetch_array($query)) {
$final[] = array($row['u1'], $row['u2'], $row['u3']);
}
There may be issues with the order and relationships of the data in these arrays (especially if all 3 tables don't have the same number of rows), but working just off the information above, this is another way you could approach it. Something to think about anyway.
Try this:
$sql = "SELECT 'user_id' FROM ".$table;
What about:
$tables = array('table_one', 'table_two', 'table_three');
$final = array();
foreach($tables as $tableIndex => $table) {
$sql = "SELECT user_id FROM ".$table;
$query = mysqli_query($con, $sql)or die(mysqli_error($con));
$i = 0;
while($row = mysql_fetch_array($query)) {
$final[$tableIndex][$i] = $row['user_id'];
$i++;
}
}
It is always better selecting only the columns you will use. SELECT * is not a good SQL practice.
Related
I want to search a certain string in all the columns of different tables, so I am looping the query through every column name. but if i give it as dynamic value it does not seem to work.
what is wrong?
<?php
$search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'feedback'";
$columns_result = $conn->query($columns);
$columns_array = array();
if (!$columns_result) {
echo $conn->error;
} else {
while ($row = $columns_result->fetch_assoc()) {
//var_dump($row);
//echo $row['COLUMN_NAME']."</br>";
array_push($columns_array, $row['COLUMN_NAME']);
}
}
var_dump($columns_array);
$row_result = array();
for ($i = 0; $i < count($columns_array); $i++) {
echo $columns_array[$i] . "</br>";
$name = "name";
// $sql = 'SELECT * FROM feedback WHERE "'.$search.'" in ("'.$columns_array[$i].'")';
$sql = 'SELECT * FROM feedback WHERE ' . $name . ' like "' . $search . '"';
$result = $conn->query($sql);
if (!$result) {
echo "hi";
echo $conn->error;
} else {
foreach ($result as $row) {
array_push($row_result, $row);
echo "hey";
}
}
}
var_dump($row_result);
I am getting the column names of the table and looping through them because I have so many other tables which I need to search that given string. I don't know if it is optimal I did not have any other solution in my mind. If someone can tell a good way I will try that.
It looks to me that you want to generate a where clause that looks at any available nvarchar column of your table for a possible match. Maybe something like the following is helpful to you?
I wrote the following with SQL-Server in mind since at the beginning the question wasn't clearly tagged as MySql. However, it turns out that with a few minor changes the query work for MySql too (nvarchar needs to become varchar):
$search='%';$tbl='feedback';
if (isset($_POST['search'])) $search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '$tbl' AND DATA_TYPE ='nvarchar'";
$columns_result = $conn->query($columns);
$columns_array = array();
if(!$columns_result) print_r($conn->errorInfo());
else while ($row = $columns_result->fetch(PDO::FETCH_ASSOC))
array_push($columns_array, "$row[COLUMN_NAME] LIKE ?");
$where = join("\n OR ",$columns_array);
$sth = $conn->prepare("SELECT * FROM $tbl WHERE $where");
for ($i=count($columns_array); $i;$i--) $sth->bindParam($i, $search);
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
The above is a revised version using prepared statements. I have now tested this latest version using PHP 7.2.12 and SQL-Server. It turned out that I had to rewrite my parameter binding part. Matching so many columns is not a very elegant way of doing queries anyway. But it has been a nice exercise.
It looks like you are using mysqli, so I wanted to give another way of doing it via mysqli.
It does more or less the same as cars10m solution.
$search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'feedback'";
$columns_result = $conn->query($columns)->fetch_all(MYSQLI_ASSOC);
// Here dynamically prepare WHERE with all the columns joined with OR
$sql = 'SELECT * FROM feedback WHERE ';
$arrayOfWHERE = [];
foreach($columns_result as $col){
$arrayOfWHERE[] = '`'.$col['COLUMN_NAME'].'` LIKE ?';
}
$sql .= implode(' OR ', $arrayOfWHERE);
// prepare/bind/execute
$stmt = $conn->prepare($sql);
$stmt->bind_param(str_repeat("s", count($arrayOfWHERE)), ...array_fill(0, count($arrayOfWHERE), $search));
$stmt->execute();
$result = $stmt->get_result();
$row_result = $result->fetch_all(MYSQLI_ASSOC);
var_dump($row_result);
Of course this will search for this value in every column of the table. It doesn't consider data type. And as always I have to point out the using PDO is better than mysqli. If you can switch to PDO.
I am fetching records as follows:
$aResult = array();
$sql = "SELECT notes FROM table WHERE user_id = '$user_id'";
$result = $conn->query($sql);
while($row = mysqli_fetch_array($result)){
$aResult['query_result'] = $row;
}
This returns only the last record in the table. I need to return all records from the sql statement.
change you $aResult['query_result'] = $row; to $aResult['query_result'][] = $row;
You've override the result each time, so you just get one.
It seems your loop constantly overwrites the value and hence you will only ever seen the last row. I think you might see better results if you do something like:
while($row = mysqli_fetch_array($result))
{
$aResult[] = $row;
}
so that each new row gets appended to your array
Try with following code, currently You are initiating the values to the same array key :
$aResult = array();
$sql = "SELECT notes FROM table WHERE user_id = '$user_id'";
$result = $conn->query($sql);
while($row = mysqli_fetch_array($result)){
$aResult['query_result'][] = $row;
}
for more Detail On Array
I have a MySQL table with groups of people who have a number attached to their name. They are either a 1,2,3 or 4. I need to create groups where there is an even distribution of members in each group. In other words, I don't want all the 4's in one group, or all the 3's in another. I'd like it to be distributed evenly.
This is what I have so far. It echo's out the people and groups them by their level, but I'm not sure how to make groups of them that equally distributes their levels.
I have some more code and even though I've pissed off the community with my lack of experience, I was hoping someone might be able to tell me how to clean up the code. It works how I want it, but it feels ugly. Any help would be greatly appreciated.
<?php
include_once 'connect.php';
$level1 = array();
$level2 = array();
$level3 = array();
$level4 = array();
$sql1 = "SELECT * FROM table WHERE level = 1";
$stmt = $handler->prepare($sql1);
$stmt->execute();
$row = $stmt->fetchAll();
foreach($row as $rows)
{
$level1[] = $rows['name'];
}
$sql2 = "SELECT * FROM table WHERE level = 2";
$stmt = $handler->prepare($sql2);
$stmt->execute();
$row = $stmt->fetchAll();
foreach($row as $rows)
{
$level2[] = $rows['name'];
}
$sql3 = "SELECT * FROM table WHERE level = 3";
$stmt = $handler->prepare($sql3);
$stmt->execute();
$row = $stmt->fetchAll();
foreach($row as $rows)
{
$level3[] = $rows['name'];
}
$sql4 = "SELECT * FROM table WHERE level = 4";
$stmt = $handler->prepare($sql4);
$stmt->execute();
$row = $stmt->fetchAll();
foreach($row as $rows)
{
$level4[] = $rows['name'];
}
$sql5 = "SELECT * FROM table";
$stmt = $handler->prepare($sql5);
$stmt->execute();
$row = $stmt->fetchAll();
$result = count($row);
for($i=0; $i<=$result; $i++)
{
echo $level1[$i];
echo"<br>";
echo $level2[$i];
echo"<br>";
echo $level3[$i];
echo"<br>";
echo $level4[$i];
echo"<br>";
}
?>
Sounds like a simple round-robin style of distribution, it requires a loop range of 1 to 4, uses that as an index to an array that accumulates counts for each group. That may solve the problem you describe, if I have understood what you have asked.
If you are still in the theoretical side of this, draw a diagram of what you mean. A code example would mean the answer could address your issue rather than address it theoretically.
I want to make select and print out all of the tables I have (I got that so far), and then limit it using `` and then ordering them by table name, and have 10 results per page.
How would I go about doing that? I know how to do it getting data from tables, but I don't know how to do it using just tables.
I have this so far:
function list_tables($type){
$sql = "SHOW TABLES FROM example";
$result = mysql_query($sql);
while($row = mysql_fetch_row($result)){
$table_name = $row[0];
echo $table_name; //edited out a lot to keep it simple
//I'm just printing out a lot of data based on table name anyway
}
mysql_free_result($result);
}
So far, it only prints out all of the table names (+ extra info I print for table names) all in the same page and it's getting the the point where it takes forever to scroll. I'd like to limit it to about 10-20 posts per page instead of a few hundred posts on one page.
Thanks in advanced if anyone can help me. Much appreciated.
Calculate the offset and limit according to the page number and try the below query:
function list_tables($type, $offset, $limit){
$sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'example' ORDER BY TABLE_NAME LIMIT $offset, $limit";
$result = mysql_query($sql);
while($row = mysql_fetch_row($result)){
$table_name = $row[0];
echo $table_name; //edited out a lot to keep it simple
//I'm just printing out a lot of data based on table name anyway
}
mysql_free_result($result);
}
Use below given query which supports LIMIT so you can do pagination with your table names.
select * from information_schema.tables LIMIT 5
i did this:
function list_tables(){
$amtperpage = 15;
$sql = "SELECT COUNT(TABLE_NAME) FROM information_schema.tables WHERE TABLE_SCHEMA = 'my_dbname'";
$result = mysql_query($sql);
$row = mysql_fetch_row($result);
$total_rows = $row[0];
//pagination stuff here
if(isset($_GET['p'])) $curpage = intval($_GET['p']); else $curpage=1;
$start = abs(($curpage-1)*amtperpage);
$sql = "SELECT TABLE_NAME FROM information_schema.tables ORDER BY TABLE_NAME ASC LIMIT $start,$per_page";
$res = mysql_query($sql);
while($row=mysql_fetch_array($res)) $DATA[++$start]=$row;
$uri = strtok($_SERVER['REQUEST_URI'],"?")."?";
$tmpget = $_GET;
unset($tmpget['p']);
if($tempget){
$uri .= http_build_query($tmpget)."&";
}
$num_pages=ceil($total_rows/$amtperpage);
for($i=1;$i<=$num_pages;$i++) $PAGES[$i]=$uri.'p='.$i;
?><div id="container">Pages:
foreach ($PAGES as $i => $link){
if($i == $curpage){
=$i
} else {
?><?=$i?>
}
} ?>
foreach($DATA as $i => $row){
$table_name = $row[0];
//use my functions to get data for each table name and list it and such
}
}
this is highly butchered since I have a lot of stuff that would've gotten in the way of the point but this should work. Thanks to the people who helped me. :)
Hie. I am trying not to place an SQL query inside a loop, since this improves performance. I think I am supposed to use implode. But can't figure out how to do it. Here is my code:
<?php
//FUNCTION CONNECTNG TO DB HERE
function turn_result_to_array($result)
{
$result_array = array();
for ($count=0; $row = mysql_fetch_array($result); $count++)
{
$result_array[$count] = $row;
}
return $result_array;
}
function get_sender_username()
{
//connect to DB
$query = sprintf("SELECT DISTINCT sender FROM direct_messages
WHERE receiver_username='%s'
ORDER BY direct_messages.id DESC",
mysql_real_escape_string($_COOKIE['username']));
$result = mysql_query($query);
$result = turn_result_to_array($result);
return $result;
}
$senders = get_sender_username();
foreach($senders as $sender)
{ //SELECT IMAGE(S) FROM USER TABLE WHERE USERNAME = $SENDERS }
Instead of putting the query inside the FOREACH, i want to put it after, so i don't make multiple round trips to the database. FYI i already know that we supposed to switch to PDO. Thanks in advance.
Here is one way of doing it:
$senderInString = implode("','",$senders);
$senderInString = "('$senderInString')";
$newQuery = "SELECT something FROM tables WHERE sender in $senderInString;"
$newResult = mysql_query($newQuery);
Use
$query= "SELECT IMAGE(S) FROM USER TABLE WHERE USERNAME IN (".implode(',',$senders).")";
$result = mysql_query($query);
In the place of foreach