Selecting MYSQL rows with same field names and adding a prefix - mysql

I'm trying to make a mysql query to select several tables and LEFT join them, however they all have same columns names 'user' etc. I want to rename all the fields in this manner . so I tried the following query
SELECT mod_backup_accounts . * AS account . * , mod_backup_subscriptions . *
FROM `mod_backup_accounts`
LEFT JOIN `mod_backup_subscriptions` ON `mod_backup_accounts`.subscription_id = `mod_backup_subscriptions`.package_id
However the mod_backup_accounts . * AS account . * makes it fail, is there a way to do this? so it would be names as account.

You cannot supply a shorthand to alias columns you must do it explicitly for each column name. In general anyway, it is typically recommended to name all columns explicitly in the SELECT list rather than using SELECT *, since it allows you to deterministically specify the column order, and protects you against accidentally pulling in a large BLOB later on if one ever gets added to the table ( or any other schema changes ).
SELECT
mod_backup_accounts.user AS account_user,
mod_backup_subscriptions.user AS subscription_user,
...
...
FROM
mod_backup_accounts
LEFT JOIN `mod_backup_subscriptions` ON `mod_backup_accounts`.subscription_id = `mod_backup_subscriptions`.package_id

I totally understand your problem about duplicated field names.
I needed that too until I coded my own function to solve it. If you are using PHP you can use it, or code yours in the language you are using for if you have this following facilities.
The trick here is that mysql_field_table() returns the table name and mysql_field_name() the field for each row in the result if it's got with mysql_num_fields() so you can mix them in a new array.
You can also modify the function to only add the "column." prefix when the field name is duplicated.
Regards,
function mysql_rows_with_columns($query) {
$result = mysql_query($query);
if (!$result) return false; // mysql_error() could be used outside
$fields = mysql_num_fields($result);
$rows = array();
while ($row = mysql_fetch_row($result)) {
$newRow = array();
for ($i=0; $i<$fields; $i++) {
$table = mysql_field_table($result, $i);
$name = mysql_field_name($result, $i);
$newRow[$table . "." . $name] = $row[$i];
}
$rows[] = $newRow;
}
mysql_free_result($result);
return $rows;
}

Related

Run query inside WP hook?

I want to use the hook from below.
The hook will run when a draft is published
function mepr_clear_cached_ids($post) {
$post_type = get_post_type($post);
if($post_type && $post_type == 'memberpressproduct') {
// Run query here.
}
}
add_action('draft_to_publish', 'mepr_clear_cached_ids');
inside the hook I want to run that query to clear the database cache of the fields on the wp_postmeta table :
DELETE FROM [prefix]_postmeta WHERE
(
meta_key LIKE '_mepr_stripe_product_id_[gateway-id]%' OR
meta_key LIKE '_mepr_stripe_plan_id_[gateway-id]%' OR
meta_key LIKE '_mepr_stripe_tax_id_[gateway-id]%' OR
meta_key LIKE '_mepr_stripe_initial_payment_product_id_[gateway-id]%' OR
meta_key LIKE '_mepr_stripe_onetime_price_id_%'
)
AND post_id IN ([memberships])
[gateway-id] - it will be replaced by the gateway id. it's a letters and numbers id.
How should the correct and best syntaxis of the query from above be added inside the hook?
This is a job for $wpdb->esc_like(), $wpdb->prepare(), and $wpdb->query(), and implode().
I assume your [gateway_id] value is in a variable called $gateway_id. And I assume your [memberships] are in an array of integers called $memberships.
You probably want to do something like this to build up and then run your query.
/* a list of the meta keys */
$metaKeysToDelete = [
"_mepr_stripe_product_id_{$gateway_id}%",
"_mepr_stripe_plan_id_{$gateway_id}%",
"_mepr_stripe_tax_id_{$gateway_id}%".
"_mepr_stripe_initial_payment_product_id_{$gateway_id}%",
"_mepr_stripe_onetime_price_id_%",
];
/* construct the LIKE clauses from the meta keys, using esc_like */
$clauses = [];
foreach ( $metaKeysToDelete as $metaKey ) {
$clauses [] = "meta_key LIKE '" . $wpdb->esc_like( $metaKey ) . '"';
}
/* construct the query */
/* debug! use SELECT * in place of DELETE to make sure you have it right */
$q = "DELETE FROM $wpdb->postmeta WHERE "
. "(" . implode( ' OR ', $clauses ) . ")"
. AND post_id IN (" . implode( ',', $memberships ) . ")";
/* debug! make sure your query is correct. */ print_r( $q );
/* prepare and run the query */
$wpdb->query( $wpdb->prepare( $q ) );
Thanks for your reply
[gateway_id] value is not a variable but gateway id. it's a letters and numbers id- similar to dewhj2_3j3.
[memberships] will be a comma separate list of the memberships ids.
If I run the query directly in the database with modified/correct data for wp prefix, gataway id and memberships ids that do the work for what the query is and it clears the metadata from the wp_postmata table for the metakeys from the query.
I want to automate the process so that when membership is published from the draft to clear the cache and the metadata for the meta keys from the query
Hope all the above makes sense.

mySQL query for building dynamically populated model

I have some code below which demonstrates a hard-coded example of what I would like to accomplish dynamically.
At a high level, I wish to do something like select * from view_data_$app_state and then get all of the data from that views table into my mustache templates dynamically.
The code I currently must use to group multiple rows of data for a specific column along with the views data is:
<?php
error_reporting(E_ALL);
class Example {
function __construct(){
try {
$this->db = new PDO('mysql:host=localhost;dbname=Example', 'root','drowssap');
}
catch (PDOException $e) {
print($e->getMessage());
die();
}
}
function __destruct(){
$this->db = null;
}
function string_to_array($links_string){
return explode(",", $links_string);
}
function get_view_data(){
$q = $this->db->prepare('select *, GROUP_CONCAT(`links`) as "links" from `view_data_global` ');
$q->execute();
$result = $q->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
$Example = new Example();
$result = $Example->get_view_data();
$result[0]["links"] = $Example->string_to_array($result[0]["links"]);
echo json_encode($result);
This gives me the perfect object while
GROUP_CONCAT seems to be doing the trick this way, however I MUST know the column name that will contain multiple rows before writing the query. I am trying to figure out an approach for this and wish to make a custom query + code example that will transform cols with multiple rows of null null and not empty data into an array like above - but return the data.. again like the code above.
Below is an output of the actual data:
[{"id":"1","title":"This is the title test","links":["main","about","store"]}];
How can I replicate this process dynamically on each view table?
Thank you so much SO!
You can use PDOStatement::fetch to retrieve your results, with fetch_style set to PDO::FETCH_ASSOC (some other values will also provide the same information). In this case, the result set will be array indexed by column name. You can access this information with foreach (array_expression as $key => $value)
See the documentation for additional information.

PHP PDO succinct mySQL SELECT object

Using PDO I have built a succinct object for retrieving rows from a database as a PHP object with the first column value being the name and the second column value being the desired value.
$sql = "SELECT * FROM `site`"; $site = array();
foreach($sodb->query($sql) as $sitefield){
$site[$sitefield['name']] = $sitefield['value'];
}
I now want to apply it to a function with 2 parameters, the first containing the table and the second containing any where clauses to then produce the same result.
function select($table,$condition){
$sql = "SELECT * FROM `$table`";
if($condition){
$sql .= " WHERE $condition";
}
foreach($sodb->query($sql) as $field){
return $table[$field['name']] = $field['value'];
}
}
The idea that this could be called something like this:
<?php select("options","class = 'apples'");?>
and then be used on page in the same format as the first method.
<?php echo $option['green'];?>
Giving me the value of the column named value that is in the same row as the value called 'green' in the column named field.
The problem of course is that the function will not return the foreach data like that. That is that this bit:
foreach($sodb->query($sql) as $field){
return $table[$field['name']] = $field['value'];
}
cannot return data like that.
Is there a way to make it?
Well, this:
$sql = "SELECT * FROM `site`"; $site = array();
foreach($sodb->query($sql) as $sitefield){
$site[$sitefield['name']] = $sitefield['value'];
}
Can easily become this:
$sql = "SELECT * FROM `site`";
$site = array();
foreach( $sodb->query($sql) as $row )
{
$site[] = $row;
}
print_r($site);
// or, where 0 is the index you want, etc.
echo $site[0]['name'];
So, you should be able to get a map of all of your columns into the multidimensional array $site.
Also, don't forget to sanitize your inputs before you dump them right into that query. One of the benefits of PDO is using placeholders to protect yourself from malicious users.

JSON encode comma delimited row

I'm trying to add an autocomplete tokenizer script to some form fields and one issue I'm having is if a person saves multiple values for the field the autocomplete suggestions come back with all of his values as one long value instead of them being single values delimited by the comma. I first tried to simply explode the value but it doesn't format it correctly in the JSON encode.
Here is my PHP file:
//connection information
$host = "localhost";
$user = "myuser";
$password = "mypass";
$database = "mydb";
$param = ($_GET["term"]);
//make connection
$server = mysql_connect($host, $user, $password);
$connection = mysql_select_db($database, $server);
//query the database
$query = mysql_query("SELECT cb_activities FROM jos_comprofiler WHERE cb_activities REGEXP '^$param'");
//build array of results
for ($x = 0, $numrows = mysql_num_rows($query); $x < $numrows; $x++) {
$row = mysql_fetch_assoc($query);
$activities[$x] = array(cb_activitiesterm => $row[cb_activities]);
}
//echo JSON to page
$response = $_GET["callback"] . "(" . json_encode($activities) . ")";
echo $response;
mysql_close($server);
This gives the output like this:
[{"cb_activities":"Kicking Cats,"},{"cb_activities":"baseball,hockey,"}]
but I need it to output like this:
[{"cb_activities":"Kicking Cats,"},{"cb_activities":"baseball,"},"cb_activities":"hockey,"}]
I also need to find a way to prevent duplicate entries from populating. For instance, the way it is now, say 10 people all have kicking cats selected as a value, it will display 10 times in the autocomplete suggestions.
How do I set this up to correctly delimit at the commas and then weed out duplicate values?
NM the duplicate issue, I just added select distinct instead of just select, this json thing has me overcomplicating things now lol. Now if I can just figure out how to delimit properly at the comma all will be good.

Adding 2 drop lists to associated table

I am having an issue trying to add the records using 2 drop lists.
I have a table called Urls which holds the details of url. I have a table called category populates a drop list, I have another table called publishers which populates another drop list.
$query = 'INSERT INTO url_associations (url_id, url_category_id, approved, url_publisher_id) VALUES ';
foreach ($_POST['types'] as $v){
$query .= "($uid, $v, 'Y', $k), ";
}
$query = substr ($query, 0, -2); // Chop off the last comma and space.
$result = #mysql_query ($query); // Run the query.
if (mysql_affected_rows() == count($_POST['types'])) { // Query ran OK.
echo '<p><b>Thank you for your submission!</b></p>';
$_POST = array(); // Reset values.
} else { // If second query did not run OK.
The code above allows me to addd data using the categories drop list but when I try to add the url_publisher_id as 'posters' as $k I keep getting errors in my parsing. If anyone can understand what I am trying to achieve your help would be welcomed
If the value of your $k variable is anything other than an integer or float you'll get an error because it needs quotes around it when you're building the SQL INSERT statement:
$query .= "($uid, $v, 'Y', '$k'), ";
Note: There are some major security problems in your example. If you put user input from $_POST into your SQL without escaping it you're giving the user the ability to run whatever SQL commands they want to run on your database.
I have added an extra array foreach ($_POST[posters] as $k)
//so it reads
'foreach ($_POST[types] as $v)
foreach ($_POST[posters] as $k) {`
and it has executed perfectly.
Thanks for your help.
Sean