PHP/SQL: Faster Way to Combine Query Results - php

I'm joining data from two SQL queries and I'm wondering if there is a faster way to do this as a single SQL query because there is a lot of looping involved. I've got two queries that look for different string values in the "option_name" field:
$sql01= "SELECT user_id, option_value FROM wp_wlm_user_options WHERE option_name = 'wpm_login_date' ORDER BY user_id";
$sql02 = "SELECT user_id, option_value FROM wp_wlm_user_options WHERE option_name ='stripe_cust_id' ORDER BY user_id ";
Then I create two arrays:
//Process the 1st SQL query data into an Array
$result_array01 = array();
$j = 0;
while($r = mysql_fetch_assoc($result01)) {
if(!empty($r['option_value'])){
//User Id and Last Login
$result_array01[$j]['user_id'] = $r['user_id'];
$result_array01[$j]['last_login'] = $r['option_value'];
$j++;
}
}
//Process the 2nd SQL query data into an Array
$result_array02 = array();
$k = 0;
while($s = mysql_fetch_assoc($result02)) {
if(!empty($s['option_value'])){
//User Id and Stripe Customer Id
$result_array02[$k]['user_id'] = $s['user_id'];
$result_array02[$k]['cust_id'] = $s['option_value'];
$k++;
}
}
And finally, I combine the arrays:
//Combine the SQL query data in single Array
$combined_array = array();
$l = 0;
foreach($result_array01 as $arr01){
// Check type
if (is_array($arr01)) {
//mgc_account_print("hello: " . $arr01['user_id'] . "\r\n");
foreach($result_array02 as $arr02){
// Check type
if (is_array($arr02)) {
//Check if User Id matches
if($arr01['user_id'] == $arr02['user_id']){
//Create Array with User Id, Cust Id and Last Login
$combined_array[$l]['user_id'] = $arr01['user_id'];
$combined_array[$l]['last_login'] = $arr01['last_login'];
$combined_array[$l]['cust_id'] = $arr02['cust_id'];
$l++;
}
}
}
}
}

Why you doing in two different queries?
Use mysql IN('val', 'val2');

$sql01= "SELECT tbl1.user_id, tbl1.option_value FROM wp_wlm_user_options as tbl1 WHERE tbl1.option_name = 'wpm_login_date'
union all
SELECT tbl2.user_id, tbl2.option_value FROM wp_wlm_user_options as tbl2. WHERE tbl2.option_name ='stripe_cust_id' ";
But using OR/AND will your help you in your case , I didnt see at first that you want combined same table. I didnt delete my answer to help you for another solution
Also you should use DISTINCT to avoid multiple records.
SELECT DISTINCT USER_ID, OPTION VALUE FROM TABLE

Related

Is there a better way to run multiple SQL queries to the same table using PHP?

I have a query that requests an ID (the PK) and an order number and throws them into an array. I then loop through the returned data in the array and run two more queries to find the number of times the order number shows up in the database and to get the invoice numbers that belong to that order number. The problem I'm seeing with this setup is that it is taking a while (around 9 seconds) to return the compiled data array. Is there a faster way to get the returned results I'm looking for?
I've tried to find some articles online and came across mysqli_multi_query. Is this the better route to make multiple queries to gather the type of data I am trying to get?
<?php
require 'config.php';
$sql = "SELECT id,internal_order_number FROM orders GROUP BY internal_order_number ORDER BY created_date desc LIMIT 0 ,50";
$query=mysqli_query($mysqli, $sql);
if (!$query) {
throw new Exception(mysqli_error($mysqli)."[ $sql]");
}
$data = array();
while( $row=mysqli_fetch_array($query) ) { // preparing an array
$nestedData=array();
$nestedData['line_id'] = $row["id"];
$nestedData['internal_order_number'] = $row["internal_order_number"];
$data[] = $nestedData;
}
$compiled_data = array();
// Loop through data array with additional queries
foreach($data as $line){
$new_data = array();
// Get item counts
$item_counts = array();
$get_count = " SELECT internal_order_number FROM orders WHERE internal_order_number = '".$line['internal_order_number']."' ";
$count_query=mysqli_query($mysqli, $get_count);
while ($counts=mysqli_fetch_array($count_query)){
if (isset($item_counts[$counts['internal_order_number']])) {
$item_counts[$counts['internal_order_number']]++;
} else {
$item_counts[$counts['internal_order_number']] = 1;
}
}
$product_count = $item_counts[$line['internal_order_number']];
// Get invoice numbers
$invoice_array = array();
$get_invoices = " SELECT invoice_number FROM orders WHERE internal_order_number = '".$line['internal_order_number']."'";
$invoice_query=mysqli_query($mysqli, $get_invoices);
while ($invoice=mysqli_fetch_array($invoice_query)){
if(!in_array($invoice['invoice_number'], $invoice_array)){
$invoice_array[] = $invoice['invoice_number'];
}
}
$invoices = implode(", ",$invoice_array);
$new_data['order_number'] = $line['internal_order_number'];
$new_data['count'] = $product_count;
$new_data['invoices'] = $invoices;
$compiled_data[] = $new_data;
}
mysqli_close($mysqli);
print_r($compiled_data);
?>
What, why are you doing basically the same query 3 times. You first one selects them all, you second query requires the same table making sure the first tables order number == the tables order number and the last just grabs the invoice number...?
Just do one query:
SELECT internal_order_number, invoice_number FROM table WHERE ...
Then loop through it and do what you need. You don't need 3 queries...

PHP optimize multiple update and select query

I have a php API where i am checking different conditions and based on that, i am fetching the count of the row and updating the count in the same table.
Below are the Conditions i am writing the query: (Note: 1 user can have multiple campaigns)
1) For a given user(Uid), for a particular campaign whose type = Impression, i am getting the Impression count and updating the same in table
2) For a given user(Uid), for a particular campaign whose type = Action i am getting the Action count and updating the same in table
//To get the Impression/Action/Lead count
$Impressionarr = [];
$Actionarr = [];
//IMPRESSION COUNT
$imp_qry = "select count(*) as ImpressionCount from ClicksAndImpressions where Uid = 101642 and CampaignID =100 and Type='Impression' ;";
$impData = $this->getClicksAndImpressionsTable()->CustomQuery($imp_qry);
if($impData[0]['ImpressionCount'] != '' || $impData[0]['ImpressionCount'] !=NULL ){
$impr_update = "UPDATE ClicksAndImpressions SET ImpressionCount = ". $impData[0]['ImpressionCount'] ." where Uid = 101642 and CampaignID =100 ;";
}else{
echo '----not Present';
}
//Impression count
foreach($impData as $key=>$data)
{
$data['ImpressionCount'];
$Impressionarr[] = $data;
}
//ACTION COUNT
$action_qry = "select count(*) as ActionCount from ClicksAndImpressions where Uid = 101617 and CampaignID =81 and Type = 'Action';";
$actionData = $this->getClicksAndImpressionsTable()->CustomQuery($action_qry);
if($actionData[0]['ActionCount'] != '' || $actionData[0]['ActionCount'] !=NULL ){
$action_update = "UPDATE ClicksAndImpressions SET ActionCount = ". $actionData[0]['ActionCount'] ." where Uid = 101617 and CampaignID =81 ;";
$actionData = $this->getClicksAndImpressionsTable()->CustomUpdate($action_update); //print_r($actionData);exit;
}else{
echo '----not Present';
}
//Action count
foreach($actionData as $key=>$data)
{
$data['ActionCount'];
$Actionarr[] = $data;
}
//Trying to combine the 3 arrays- but 2nd and 3rd not merging into 1st
$combine = array_merge($CampaignDetailsarr,$Impressionarr,$Actionarr);
1) Can the above duplicates - either in Update query or multiple for loops be avoided. if so how to optimize the above as per my conditions
ie) For
if( Uid = 123 for some campaignId = 11 and if type is 'Impression')
-> Update query for impression
else if(Uid = 123 for campaignId= 22 and if type = 'something else')
-> Update query for something else
2) I already have one array 1. I need to merge my 2 new arrays (Impressionarr[], Actionarr[]) into the 1st one, but below is how im getting.
Expected:
Coming as:
You could probably speed it up by creating a stored procedure in your database and calling that with the required data. From what I can see, most of the logic you have to do can be done in the stored procedure.

SELECT a value multiple time in SQL

I have a code in PHP where I want to display multiple times values, and so, even if these values are the same between them. My code is simple :
$sql = "SELECT photo from table WHERE username IN ('1','2','2') ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result)){
array_push($res, $row['photo']);
}
echo json_encode($res);
But this code only display (in json) an array of two values (because the values of photo of the username 2 are the same).
What I want to achieve is to make an array with the exact same number of values of the number of username I defined WHERE username IN ('1','2','2') (so here, 3 values).
I hope you understood me, thanks for helping me !
I think what you're after is to list even the duplicates in the end result. As your SQL will only retrieve the unique items, the idea would be to include the username in the SQL result set. Then use the original list of user names ($userNames) and add in the photo for each of them.
I've used mysqli_fetch_all() to simplify the process of fetching all of the data, then used array_column() to make the username the key for the photos.
$userNames = array(1,2,2);
$sql = "SELECT username, photo
from table
WHERE username IN ('".implode("','", $userNames)."')
ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
$photos = mysqli_fetch_all($result, MYSQLI_ASSOC);
$photos = array_column($photos, "photo", "username");
foreach ( $userNames as $user ) {
if ( isset($photos[$user])) {
$res[] = $photos[$user];
}
else {
$res[] = '';
}
}
echo json_encode($res);
You would use left join:
select t.photo
from (select '1' as username union all select '2' union all select '3'
) u left join
table t
on t.username = u.username
order by t.id desc;
Note this will return rows, even when the user name does not exist. If you want to filter those rows, remove the left so you are doing an inner join.

Search query and ordering by matches with my sql

Hi am currently stuck here, been doing research on how to write a mysql statement for a flexible search for products and order them by relevance on a project am working on have seen a few but wasn't helpful please i need help on how to make it work, my current method doesn't work, here it is.
User types in search field and submits "iPad 3rd Generation".
My script breaks the string into words like so.
$termsExploded = array_unique(explode(' ', $term));
No i use php to create an sql query based on the number of words found.
$i = 0;
foreach ($termsExploded as $word) {
if (strlen($word)>1) {
if ($i == 0) {
$where_query = $where_query." name LIKE '%".$word."%'";
}
else{
$where_query = $where_query." OR name LIKE '%".$word."%'";
}
$i++;
}
}
The where query variable now looks like this.
name Like '%ipad%' Or name Like '%3rd%' Or name Like '%Generation%'
Now search for the products ids like so.
$IDs = "SELECT DISTINCT id FROM store_items WHERE".$where_query;
I now create a second where query based on the IDs returned like so
$where_query_s = null;
$i = 0;
foreach ($IDs as $result) {
$returnID = $result->id;
if ($i == 0) {
$where_query_s = $where_query_s." id = ".$returnID."";
}
else{
$where_query_s = $where_query_s." OR id = ".$returnID."";
}
$i++;
};
Now i select the products again based on the distinct IDs returned like so
$items = "SELECT * FROM store_items WHERE".$where_query_s;
Now this works to get the products but how can i sort it based on best match?
Assuming you want to order by the number of matches then build up another string as follows:-
ORDER BY IF(name Like '%ipad%', 1, 0) + IF(name Like '%3rd%', 1, 0) + IF(name Like '%Generation%', 1, 0) DESC
But this will be slow, and takes no account of indexing to improve performance nor of plural / singular (ie, it someone searches for 'flies' it won't rank 'fly' properly).
To put that more into code:-
$where_query = array();
$order_query = array();
foreach ($termsExploded as $word)
{
if (strlen($word)>1)
{
$where_query[] = " name LIKE '%".$word."%'"
$order_query[] = " IF(name Like '%".$word."%', 1, 0)"
}
}
$IDs = "SELECT DISTINCT id FROM store_items WHERE ".implode(' OR ', $where_query)." ORDER BY ".implode(' + ', $order_query)." DESC";
Arrange for your query to look like this:
select field1, field2, etc, count(*) records
from store_items
where blah blah blah
group by field1, field2, etc
order by records desc
If the table is MyISAM based or if it is InnoDB and the version is Mysql 5.6 or greater, then you can use full text search (see http://dev.mysql.com/doc/refman/5.6/en/fulltext-search.html)
effectively you want a query similar to
SELECT * FROM store_items WHERE MATCH (name) AGAINST ('iPad 3rd Generation')
ORDER BY MATCH (name) AGAINST ('iPad 3rd Generation')

Displaying 5 rows of data from query

I have a simple table (mgap_orders) with customer orders in it. Multiple have the the same id (mgap_ska_id) and I simply want to pull 5 records from the table and display all five.
I can easily get one record with the following query and PDO, but how can I display 5 rows instead of only one row?
$result_cat_item = "SELECT * FROM mgap_orders WHERE mgap_ska_id = '$id' GROUP BY mgap_ska_id";
while($row_cat_sub = $stmt_cat_item->fetch(PDO::FETCH_ASSOC))
{
$item=$row_cat_sub['mgap_item_description'];
$item_num=$row_cat_sub['mgap_item_number'];
$item_type=$row_cat_sub['mgap_item_type'];
$item_cat=$row_cat_sub['mgap_item_catalog_number'];
$item_ven=$row_cat_sub['mgap_item_vendor'];
$item_pur=$row_cat_sub['mgap_item_percent_purchased'];
$item_sales=$row_cat_sub['mgap_item_sales'];
}
Use limit 5 then put the results in an array, like this:
$result_cat_item = "SELECT * FROM mgap_orders WHERE mgap_ska_id = '$id' GROUP BY mgap_ska_id LIMIT 5";
$items = array();
while($row_cat_sub = $stmt_cat_item->fetch(PDO::FETCH_ASSOC))
{
$items['item'] = $row_cat_sub['mgap_item_description'];
$items['item_num'] = $row_cat_sub['mgap_item_number'];
$items['item_type'] = $row_cat_sub['mgap_item_type'];
$items['item_cat'] = $row_cat_sub['mgap_item_catalog_number'];
$items['item_ven'] = $row_cat_sub['mgap_item_vendor'];
$items['item_pur'] = $row_cat_sub['mgap_item_percent_purchased'];
$items['item_sales'] = $row_cat_sub['mgap_item_sales'];
}
Then you can do:
foreach($items as $item) {
// echo $item['item'] or whatever
}
EDIT: Or you can skip putting them in the array and just use the while() to do what you need to do with the data.

Categories