Showing all results also when not present in 2nd optional database - php

An explaination of how my code works:
I have a pure select on a database that is filled through a different program. I am selecting data to check up on orders. Now I want to give a ready status to the order, which cannot be inserted into the database I am selecting from, so I created a small different database to insert the ordernumber (from the previous selection) into that database and insert a 1. This can be updated to a 0 by pressing the button again.
Now I want to show my orders as the following:
An order can have the status, but doesn't have to have a status.
If it doesnt have a status it should show in the list.
With my current code (below) it only shows orders that are present in the 2nd optional database, I understand why this is happening. But I can't manage to work out a solution to show everything even if an ordernumber is not present in the 2nd optional database.
while( $row = sqlsrv_fetch_array( $stmt1, SQLSRV_FETCH_ASSOC) ) {
$statusorder = $row['ordernr']; //Ordernumber selected in primary database
$sqlstatus = "SELECT status from status WHERE Ordernr = '$statusorder'"; //selecting the status from optional database
$result = $conn2->query($sqlstatus);
while($row2 = $result->fetch_assoc()) {
<insertmyhtmlhere>
}
}

You can use only one query to get all data. Just use database.Table.column
This will display all order id of table database1.ordersTable
SELECT db1.id FROM database1.`ordersTable` db1
This will display all status of table database2.statusTable
SELECT db2.status FROM database2.`statusTable` db2
Now just combine with LEFT JOIN to show all rows whether it exists or not.
SELECT db1.id, db2.`status`
FROM database1.`ordersTable` db1
LEFT JOIN database2.`statusTable` db2
ON db1.`id` = db2.`status`;
DonĀ“t forget to use Condition to filter, in this case, the same order id.
ON db1.`id` = db2.`status`;
If databases haves different COLLATION you can use this:
SELECT db1.`id', db2.`status`
FROM database1.`ordersTable` COLLATE utf8mb4_spanish_ci db1
LEFT JOIN database2.`statusTable` COLLATE utf8mb4_spanish_ci db2
ON db1.`id` = db2.`status`;
Here are a sample fiddle

Related

How to Display data from 2 different Database

I have an hard time to retrieve data in a table from MySQL database.
I have 2 different database that cannot be merge but there is a table in the first database that is identical to the second database.
Description Database 1 table: areas : ar_id, name, password.
Description Database 2 table: user : id, username, pass.
Now, When the user Login, He logs in the 2nd database. in each page of the user I have use $_SESSION['username'] to call the username.
Importantly, In every page, I have table that displays data from different tables using the username in the 2 Database; this else the SQL to be specific and only provide each user with their own information. and That's Ok. This is the SQL:
SELECT Client_table.Name, Client_table.Client_Id FROM Client_table, user WHERE user.username = '" . $_SESSION['username'] . "' AND Client_table.Branch = user.area Order by Name ASC
In one of the page, I totally using the 1st Database with this SQL to display data in the table :
select site_id, site_name from sites WHERE srep_id = 5
AND status = 1 or status = 2
order by site_name asc
QUESTION: I would like to display this SQL data in a table by using the username or id from the 2nd database BUT is returns Empty Table (I include both Database in this page). This is my current SQL but still not displaying anything:
SELECT cl.client_name, st.site_id, st.site_name
FROM Database1.sites st
JOIN Database2.user u ON u.id = st.ar_id
JOIN Database1.clients cl ON cl.client_id = st.client_id
WHERE Database1.st.name = '".$_SESSION['username']."'
AND st.status > 0
ORDER BY st.site_name ASC
NOTE: This is a major problem that took me almost a week!
Please some one help!
I think I have an answer.
After browsing and doing some search, I sound that I can make use of the $_SESSION here and Also, This was my final SQL Statement that Helped me to Connect the 2 Database from the same SQL Statement by using variable in PHP Script.
session_start();
$result = mysql_query("SELECT cl.client_name, st.site_id, st.site_name, ar.rep_id
FROM sites st
JOIN areas ar ON ar.rep_id = st.srep_id
JOIN clients cl ON cl.client_id = st.client_id
WHERE st.srep_id = '".$_SESSION['userarea']."'
AND st.status > 0
ORDER BY st.site_name ASC");

How to handle/optimize thousands of different to executed SELECT queries?

I need to synchronize specific information between two databases (one mysql, the other a remote hosted SQL Server database) for thousands of rows. When I execute this php file it gets stuck/timeouts after several minutes I guess, so I wonder how I can fix this issue and maybe also optimize the way of "synchronizing" it.
What the code needs to do:
Basically I want to get for every row (= one account) in my database which gets updated - two specific pieces of information (= 2 SELECT queries) from another SQL Server database. Therefore I use a foreach loop which creates 2 SQL queries for each row and afterwards I update those information into 2 columns of this row. We talk about ~10k Rows which needs to run thru this foreach loop.
My idea which may help?
I have heard about things like PDO Transactions which should collect all those queries and sending them afterwards in a package of all SELECT queries, but I have no idea whether I use them correctly or whether they even help in such cases.
This is my current code, which is timing out after few minutes:
// DBH => MSSQL DB | DB => MySQL DB
$dbh->beginTransaction();
// Get all referral IDs which needs to be updated:
$listAccounts = "SELECT * FROM Gifting WHERE refsCompleted <= 100 ORDER BY idGifting ASC";
$ps_listAccounts = $db->prepare($listAccounts);
$ps_listAccounts->execute();
foreach($ps_listAccounts as $row) {
$refid=$row['refId'];
// Refsinserted
$refsInserted = "SELECT count(username) as done FROM accounts WHERE referral='$refid'";
$ps_refsInserted = $dbh->prepare($refsInserted);
$ps_refsInserted->execute();
$row = $ps_refsInserted->fetch();
$refsInserted = $row['done'];
// Refscompleted
$refsCompleted = "SELECT count(username) as done FROM accounts WHERE referral='$refid' AND finished=1";
$ps_refsCompleted = $dbh->prepare($refsCompleted);
$ps_refsCompleted->execute();
$row2 = $ps_refsCompleted->fetch();
$refsCompleted = $row2['done'];
// Update fields for local order db
$updateGifting = "UPDATE Gifting SET refsInserted = :refsInserted, refsCompleted = :refsCompleted WHERE refId = :refId";
$ps_updateGifting = $db->prepare($updateGifting);
$ps_updateGifting->bindParam(':refsInserted', $refsInserted);
$ps_updateGifting->bindParam(':refsCompleted', $refsCompleted);
$ps_updateGifting->bindParam(':refId', $refid);
$ps_updateGifting->execute();
echo "$refid: $refsInserted Refs inserted / $refsCompleted Refs completed<br>";
}
$dbh->commit();
You can do all of that in one query with a correlated sub-query:
UPDATE Gifting
SET
refsInserted=(SELECT COUNT(USERNAME)
FROM accounts
WHERE referral=Gifting.refId),
refsCompleted=(SELECT COUNT(USERNAME)
FROM accounts
WHERE referral=Gifting.refId
AND finished=1)
A correlated sub-query is essentially using a sub-query (query within a query) that references the parent query. So notice that in each of the sub-queries I am referencing the Gifting.refId column in the where clause of each sub-query. While this isn't the best for performance because each of those sub-queries still has to run independent of the other queries, it would perform much better (and likely as good as you are going to get) than what you have there.
Edit:
And just for reference. I don't know if a transaction will help here at all. Typically they are used when you have several queries that depend on each other and to give you a way to rollback if one fails. For example, banking transactions. You don't want the balance to deduct some amount until a purchase has been inserted. And if the purchase fails inserting for some reason, you want to rollback the change to the balance. So when inserting a purchase, you start a transaction, run the update balance query and the insert purchase query and only if both go in correctly and have been validated do you commit to save.
Edit2:
If I were doing this, without doing an export/import this is what I would do. This makes a few assumptions though. First is that you are using a mssql 2008 or newer and second is that the referral id is always a number. I'm also using a temp table that I insert numbers into because you can insert multiple rows easily with a single query and then run a single update query to update the gifting table. This temp table follows the structure CREATE TABLE tempTable (refId int, done int, total int).
//get list of referral accounts
//if you are using one column, only query for one column
$listAccounts = "SELECT DISTINCT refId FROM Gifting WHERE refsCompleted <= 100 ORDER BY idGifting ASC";
$ps_listAccounts = $db->prepare($listAccounts);
$ps_listAccounts->execute();
//loop over and get list of refIds from above.
$refIds = array();
foreach($ps_listAccounts as $row){
$refIds[] = $row['refId'];
}
if(count($refIds) > 0){
//implode into string for use in query below
$refIds = implode(',',$refIds);
//select out total count
$totalCount = "SELECT referral, COUNT(username) AS cnt FROM accounts WHERE referral IN ($refIds) GROUP BY referral";
$ps_totalCounts = $dbh->prepare($totalCount);
$ps_totalCounts->execute();
//add to array of counts
$counts = array();
//loop over total counts
foreach($ps_totalCounts as $row){
//if referral id not found, add it
if(!isset($counts[$row['referral']])){
$counts[$row['referral']] = array('total'=>0,'done'=>0);
}
//add to count
$counts[$row['referral']]['total'] += $row['cnt'];
}
$doneCount = "SELECT referral, COUNT(username) AS cnt FROM accounts WHERE finished=1 AND referral IN ($refIds) GROUP BY referral";
$ps_doneCounts = $dbh->prepare($doneCount);
$ps_doneCounts->execute();
//loop over total counts
foreach($ps_totalCounts as $row){
//if referral id not found, add it
if(!isset($counts[$row['referral']])){
$counts[$row['referral']] = array('total'=>0,'done'=>0);
}
//add to count
$counts[$row['referral']]['done'] += $row['cnt'];
}
//now loop over counts and generate insert queries to a temp table.
//I suggest using a temp table because you can insert multiple rows
//in one query and then the update is one query.
$sqlInsertList = array();
foreach($count as $refId=>$count){
$sqlInsertList[] = "({$refId}, {$count['done']}, {$count['total']})";
}
//clear out the temp table first so we are only inserting new rows
$truncSql = "TRUNCATE TABLE tempTable";
$ps_trunc = $db->prepare($truncSql);
$ps_trunc->execute();
//make insert sql with multiple insert rows
$insertSql = "INSERT INTO tempTable (refId, done, total) VALUES ".implode(',',$sqlInsertList);
//prepare sql for insert into mssql
$ps_insert = $db->prepare($insertSql);
$ps_insert->execute();
//sql to update existing rows
$updateSql = "UPDATE Gifting
SET refsInserted=(SELECT total FROM tempTable WHERE refId=Gifting.refId),
refsCompleted=(SELECT done FROM tempTable WHERE refId=Gifting.refId)
WHERE refId IN (SELECT refId FROM tempTable)
AND refsCompleted <= 100";
$ps_update = $db->prepare($updateSql);
$ps_update->execute();
} else {
echo "There were no reference ids found from \$dbh";
}

How to Update records with field of same records using single query?

I have one user table with column name id,father_email,mother_email,email_notification and many more, now i want to update email_notification column with
father_email,mother_email I did it with multiple queries but i want to know that how to do it with single query only so it saves the execution time.
my code are as follows:
<?php
$qry="SELECT id,CONCAT(father_email,',',mother_email) as notify FROM user";
$query=mysql_query($qry);
while($row=mysql_fetch_assoc($query))
{
$qry2="UPDATE user SET email_notification='".$row['notify']."' WHERE id=".$row['id']."";
mysql_query($qry2);
}
?>
its working fine but i want to know how to do it with single query
This will update all email_notification columns for all users:
UPDATE user
SET email_notification = CONCAT_WS(',', father_email, mother_email)
(i think it's better to use CONCAT_WS that will skip null values in father_email or in mother_email)
This will replace all of them
UPDATE user AS u
INNER JOIN user AS ul ON ul.id = u.id
SET u.email_notification = CONCAT(ul.father_email,',',ul.mother_email)
UPDATE user
SET email_notification = CONCAT_WS(',', father_email, mother_email)

display related records from my database using php

i want to display record related to a specific primary key based on the foreign keys in other tables. How to display records for that primary key in other tables using php??
for example:
table1
primary key 1: plate#1
primary key 2: plate#2
primary key 3: plate#3
table2
primary key 1: destination|route|revenue|plate# 1
primary key 2: destination|route|revenue|plate# 3
table3
primary key 1: diesel price|number of liters|plate# 1
primary key 2: diesel price|number of liters|plate# 3
I already created a page that will display all the data in table1. I want to display the data in table1 and table2 that are related to the data in table1 when I made the database they already had relationship with each other. My problem is just displaying the record related to table1. I want to display records for just plate#1, another for plate#2 and so on.
Here's a crude example:
<?php
$truck_id = mysql_real_escape_string($_GET['truck_id']);
$sql_PK = "SELECT * FROM table1 WHERE id = '{$truck_id}'";
$res_PK = mysql_query($sql_PK);
$row_PK = mysql_fetch_assoc($res_PK);
$truck_plate = $row_PK['plate'];
$truck_plate = mysql_real_escape_string($truck_plate);
$sql = "SELECT table2.plate, table2.destination, table2.route, table3.plate, table3.diesel_price, table3.num_of_liters FROM table2, table3 WHERE table2.plate = table3.plate AND table2.plate = '{$truck_plate}'";
$res = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_array($res);
// this will give you the details from the following
//TABLE2
// plate
// destination
// route
//TABLE3
// plate
// diesel_price
// num_of_liters
?>
There's a couple of important things to remember. First is get in the habit of naming your fields without spaces in the database and use _ instead. so diesel price is diesel_price, etc. Secondly is to make sure that you are protecting yourself from any injections like I have shown here using the mysql_real_escape_string
So when someone clicks on truckdetails.php?plate=mrtchi it's going to query the database based on the plate number: mrtchi
You are probably looking to join tables to get the final results. Join allows you to essentially merge tables together and get a single result based on the selections. Google php mysql join table and look at some of the examples. Here's one for you: Join Tables

PHP/ MYSQL Inserting Data Into Multiple Tables

I am trying to add data into 3 table using PHP, atm I can only view the results of the tables that are joined .
RESULTS QUERY
$sql = mysql_query("SELECT PART_ID, PART_DESC, SERIAL_NUM, PART.RACK_NUM, PART.PART_TYPE_ID, PART_TYPE_DESC, LOCATION
FROM PART
INNER JOIN PART_TYPE ON PART.PART_TYPE_ID = PART_TYPE.PART_TYPE_ID
INNER JOIN RACK ON RACK.RACK_NUM = PART.RACK_NUM
This will get all the rows from the PART table, and for each of the rows we find, match that row to a row in the PART_TYPE table (the condition being that they have the same PART_TYPE_ID). If no match between the PART and PART_TYPE tables can be found for a given row in the PART table, that row will not be included in the result.
My Insert Query This is where im having trouble
How do I add the data to the PART_ID, PART_TYPE and RACK tables?
<?php
// Parse the form data and add inventory item to the system
if (isset($_POST['PART_ID'])) {
$id = mysql_real_escape_string($_POST['PART_ID']);
$PART_DESC = mysql_real_escape_string($_POST['PART_DESC']);
$SERIAL_NUM = mysql_real_escape_string($_POST['SERIAL_NUM']);
$RACK_NUM = mysql_real_escape_string($_POST['RACK_NUM']);
$PART_TYPE_ID = mysql_real_escape_string($_POST['PART_TYPE_ID']);
$LOCATION = mysql_real_escape_string($_POST['LOCATION']);
$PART_TYPE_DESC = mysql_real_escape_string($_POST['PART_TYPE_DESC']);
// See if that product name is an identical match to another product in the system
$sql = mysql_query("SELECT PART_ID FROM PART WHERE PART_ID='$id' LIMIT 1");
$productMatch = mysql_num_rows($sql); // count the output amount
if ($productMatch > 0) {
echo 'Sorry you tried to place a duplicate "Product Name" into the system, click here';
exit();
}
// Add this product into the database now
**$sql = mysql_query("INSERT INTO PART (PART_ID, PART_DESC, SERIAL_NUM, RACK_NUM, PART_TYPE_ID)
VALUES('$id','$PART_DESC','$SERIAL_NUM','$RACK_NUM','$PART_TYPE_ID')") or die (mysql_error());**
header("location: inventory_list.php");
exit();
}
?>
Micheal if I understood your problem you just need to do 2 other SQL INSERT to add data in the other table
$sql = mysql_query("INSERT INTO PART (PART_ID, PART_DESC, SERIAL_NUM, RACK_NUM, PART_TYPE_ID)
VALUES('$id','$PART_DESC','$SERIAL_NUM','$RACK_NUM','$PART_TYPE_ID')") or die (mysql_error());
$currentID = mysql_inserted_id();
$sql2 = mysql_query("INSERT INTO PART_TYPE [..]");
$sql3 = mysql_query("INSERT INTO RACK [..]");
You can use $currentID if you need the ID of the last record inersted into PART
But still I strongly suggest you to learn PDO http://php.net/pdo for sql
your table management is wrong, you never use arrows just to show that you are joining it with that table from this table, but rather from the key in first table to foreign key in the second table, that's what i would start from, maybe a better idea would be to join them using JOIN look up in google how joins are working, that may be the cause...
I agree with #yes123, that is the correct way to insert into tables, if you have a program called heidisql then use it, because there is a window to run your queries... that way to test if it is properly written also use mysql_error.
Debug, debug, and one more time debug your code.
Your tables are not correctly designed.
Try this table structures .
In your base table Part. -
The columns in this should be:
Part_id
part_desc
serial_num
The part_type should have following columns:
part_type_id
part_type_desc
part_id -> foreign key to the parent table
The rack table should be:
Rack_num
location
part_id -> foreign key to the parent table.
So your select query to get all the part related information would be:
$sql="select * from part join part_type pt on tp.part_id=part.part_id join Rack_num rn on rn.part_id=part.part_id";
With this structure the data remains normalized. And is flexible, so if the parts are on multiple racks you just go to the rack table and add and new rack number and the part id.

Categories