I want to fetch data from the database. I have three tables in my database: listing_master_residential, listing_master_condo and listing_master_commercial. There is one primary key, Ml_num, in all tables. I want to search the data from one table which matches mls number table.
if (isset($_POST['search'])) {
$mls=$_POST['mls_number'];
$sql = "SELECT * FROM listing_master_residential,
listing_master_condo,
listing_master_commercial
INNER JOIN listing_master_residential AS res ON res.Ml_num=Ml_num
INNER JOIN listing_master_condo AS con ON con.Ml_num=Ml_num
INNER JOIN listing_master_commercial AS com ON com.Ml_num=Ml_num
WHERE Ml_num='$mls'";
$result = $wpdb->get_results($sql) or die(mysql_error());
foreach ( $result as $row) {
echo $row->Lot_code."<br/>";
echo $row->Ml_num."<br/>";
echo $row->Acres;
echo $row->Addr."<br/>";
echo $row->Bath_tot;
echo $row->Br;
echo $row->Br_plus;
}
}
With the above, I get an error:
Column 'Ml_num' in where clause is ambiguous
Because the column Ml_num is in all the tabels you need to address it with the Fully Qualified Name, for instance con.Ml_num
I did also notice your joining all the tabels twice, once with implicit join and once with ANSI join
The implicit join will result in a cross join because there are no join conditions in the where clause.
Related
I created a whole bunch of SQLite database tables. Many columns in the tables have names with spaces, which I'm now realizing was not such a brilliant idea. Is there a way to write one command which will get rid of all spaces in all columns in all tables? I know I can do it one at a time (all potential duplicates seem to address this issue rather than my issue) but it's going to take me forever. Any ideas on how I can do this?
Use the following SQL to find all of the column names that contain spaces. I also included SQL to generate a new name.
SELECT t.name as tablename, c.name as badcol, replace(c.name, ' ','_') as newcolname
FROM sqlite_master t
JOIN pragma_table_info(t.name) c
WHERE t.type = 'table' AND c.name like '% %';
From here you would have to generate alter statements looking like this:
ALTER table <tablename> RENAME COLUMN <badcol> to <newcolname>;
While I cant figure how to directly pass the list of parms to the Alter table command you can use the following SQL to generate the alter commands for you then just copy/paste the result and execute the list of them.
SELECT ('ALTER TABLE ' || t.name || ' RENAME COLUMN ' || '[' || c.name || ']'
|| ' TO ' || '[' || REPLACE(c.name, ' ','_') || '];')
FROM sqlite_master t
JOIN pragma_table_info(t.name) c
WHERE t.type = 'table' AND c.name like '% %';
In this SQL I replaced the spaces in col names with underscores but you can see where you could replace the REPLACE function with the column renaming solution you desire.
I want to select columns from users and usermeta tables.
This is my query:
$sql = $wpdb->prepare(
"SELECT {$wpdb->users}.ID FROM {$wpdb->users}
WHERE {$wpdb->users}.user_registered <= '%s'
AND {$wpdb->usermeta}.meta_key='custom_status'
AND {$wpdb->usermeta}.meta_value=0
INNER JOIN {$wpdb->usermeta} ON {$wpdb->users}.ID= {$wpdb->usermeta}.user_id", $before);
, but it doesn't select nothing. I know that I have one user with this meta_value and user_registered less than the current date time ($before).
This is what $before is like: 2019-07-06 19:03:55
The problem is that you're wrapping the %s placeholder in single quotes. That's not needed because WordPress will replace all instances of %s with a proper string containing the value you passed to the prepare() method.
So, taking that into consideration, your code becomes:
$sql = $wpdb->prepare(
"SELECT {$wpdb->users}.ID FROM {$wpdb->users}
WHERE {$wpdb->users}.user_registered <= %s
AND {$wpdb->usermeta}.meta_key='custom_status'
AND {$wpdb->usermeta}.meta_value=0
INNER JOIN {$wpdb->usermeta} ON {$wpdb->users}.ID= {$wpdb->usermeta}.user_id", $before);
Additionally, the INNER JOIN ... part of your query has to be placed before your WHERE clause or else MySQL will throw an invalid syntax error:
$sql = $wpdb->prepare(
"SELECT {$wpdb->users}.ID FROM {$wpdb->users}
INNER JOIN {$wpdb->usermeta} ON {$wpdb->users}.ID= {$wpdb->usermeta}.user_id
WHERE {$wpdb->users}.user_registered <= %s
AND {$wpdb->usermeta}.meta_key='custom_status'
AND {$wpdb->usermeta}.meta_value=0", $before);
I want to only list products that can be shipped to a customer based on their location set in billing/shipping address. (All my users are logged in)
Each of my vendors may ship to certain countries only so I don't want to show products to a user that cannot be shipped to them.
To tackle this problem I have added an extra field in the edit vendor page which saves the countries (via multi select box) they can ship to as a separate term meta.
update_term_meta($term_id, 'vendor_data_shipping_countries', $selected_shipping_countries);
etc...
All that data saves fine and is outputted as follows when I call get_term_meta($term->term_id, 'vendor_data_shipping_countries')[0].
Array
(
[0] => FR
[1] => GB
)
What I am having trouble with now is filtering the product loop query to only show products that can be shipped to the user with the action 'woocommerce_product_query'.
function ac_vendor_show_deliverable_products($query)
{
// magical query filter here...
// if users location matches any of the vendor products ship to countries then output the product to the user
// $query->set(); ... something...
}
add_action('woocommerce_product_query','ac_vendor_show_deliverable_products');
This is where my skill level fails me. I am fairly new to WC and not good at manipulating the query with actions. Better at just writing the full SQL but feel I would mess lots of other things up and filtering is the best way to go.
I expect someone's kunfu is way stronger than mine! Can anyone figure this out?
Hope someone can help.
UPDATE:
I have managed to write exactly what I want to happen in SQL
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id)
LEFT JOIN wp_termmeta ON (wp_termmeta.term_id = wp_term_taxonomy.term_id)
WHERE wp_termmeta.meta_key = 'vendor_data_shipping_countries'
AND wp_termmeta.meta_value LIKE '%"GB"%'
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC LIMIT 0, 12
This only lists products that have added GB as a country they can ship to.
Note the meta_value is stored as a serialized array so the easiest way to match was to perform a LIKE as values are stored as a:2:{i:0;s:2:"FR";i:1;s:2:"GB";} for example.
If anyone can figure out how to put that SQL into the woocommerce_product_query hook then that would be amazing. But I can't for the life of me figure out how this is possible...
Everything on https://codex.wordpress.org/Class_Reference/WP_Query just adds SQL for wp_postmeta not wp_termmeta from what I can see.
Cheers
I managed to get this to work by using the posts_join and posts_where filters instead.
I hope this helps someone else down the line.
/*
* Add the needed term tables
*/
function ac_vendor_sql_join_term_meta($join)
{
global $wp_query, $wpdb;
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
$join .= ' LEFT JOIN '. $wpdb->term_relationships .' tr1 ON (tr1.object_id = '. $wpdb->posts .'.ID)';
$join .= ' LEFT JOIN '. $wpdb->term_taxonomy .' tt1 ON (tt1.term_taxonomy_id = tr1.term_taxonomy_id)';
$join .= ' LEFT JOIN '. $wpdb->termmeta .' tm1 ON (tm1.term_id = tt1.term_id)';
}
return $join;
}
add_filter('posts_join', 'ac_vendor_sql_join_term_meta');
/*
* Add the needed where statements
*/
function ac_vendor_sql_filter_shipping_where($where, $wp_query)
{
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
//get the users billing country code.
if(is_user_logged_in())
{
$billing_country = get_user_meta(get_current_user_id(), 'billing_country', TRUE);
}
else //default to IP location
{
$geo_locate = WC_Geolocation::geolocate_ip($_SERVER['REMOTE_ADDR']);
$billing_country = $geo_locate['country'];
}
$where .= " AND tm1.meta_key = 'vendor_data_shipping_countries'";
$where .= " AND tm1.meta_value LIKE '%\"". $billing_country ."\"%'";
}
return $where;
}
add_filter('posts_where', 'ac_vendor_sql_filter_shipping_where', 10, 2);
I'm trying to use this query:
MySQL SELECT DISTINCT by highest value
SELECT
p.*
FROM
product p
INNER JOIN
( SELECT
magazine, MAX(onSale) AS latest
FROM
product
GROUP BY
magazine
) AS groupedp
ON groupedp.magazine = p.magazine
AND groupedp.latest = p.onSale ;
Within Symfony2 and DQL.
I have:
$query = $em->createQuery("SELECT p FROM MyBundle:Product p WHERE p.type = 'magazine' AND p.maglink IS NOT NULL OR (p.type = 'magazine' AND p.diglink IS NOT NULL) GROUP BY p.magazine ORDER BY p.onSale DESC");
Which works fine with and outputs objects but without the correct MAX(onSale)
Doing:
$query = $em->createQuery("SELECT p , MAX(p.onSale) FROM MyBundle:Product p WHERE p.type = 'magazine' AND p.maglink IS NOT NULL OR (p.type = 'magazine' AND p.diglink IS NOT NULL) GROUP BY p.magazine ORDER BY p.onSale DESC");
Results in non-objects being returned.
This:
$query = $em->createQuery("SELECT
p.*
FROM
MyBundle:Product p
INNER JOIN
( SELECT
p.magazine, MAX(onSale) AS p.latest
FROM
MyBundle:Product p
GROUP BY
p.magazine
) AS groupedp
ON groupedp.magazine = p.magazine
AND groupedp.latest = p.onSale ;");
Throws this error:
[Semantical Error] line 0, col 127 near 'SELECT
': Error: Identification Variable ( used in join path expression but was not defined before.
I assume due to this Symfony2 Doctrine query
How can I maintain my mapping while still being able to sort each item by onsale?
Have you considered splitting this into two queries:
First:
Run your query directly against the database connection, and return the IDs of the relevant rows, in the order you want. This separates your complex query from DQL.
Second:
Query the rows through Doctrine to get the full entities you want, based on the IDs/orders of the previous query.
This is a shot in the dark, but it seems fairly obvious. Your aliasing two tables to the same alias. Thus when your using p. in the join it thinks your working from the original definition of p from before the join, then you alias the join as p. Change the alias of the join (and the references to that table) so each alias is unique.
I wish to retrieve some nids from my drupal database. I have a query that I wish to run.
SELECT node.nid AS projectnid
FROM node node
INNER JOIN content_type_project node_data_field_project_client ON node.vid = node_data_field_project_client.vid
WHERE node_data_field_project_client.field_project_client_nid = (SELECT node_data_field_profile_company.field_profile_company_nid AS company_nid
FROM node node LEFT JOIN content_type_profile node_data_field_profile_company ON node.vid = node_data_field_profile_company.vid WHERE node.nid = 218)
I am calling the query by using:
$query =
"
SELECT node.nid AS projectnid
FROM node node
INNER JOIN content_type_project node_data_field_project_client ON node.vid = node_data_field_project_client.vid
WHERE node_data_field_project_client.field_project_client_nid = (SELECT node_data_field_profile_company.field_profile_company_nid AS company_nid
FROM node node LEFT JOIN content_type_profile node_data_field_profile_company ON node.vid = node_data_field_profile_company.vid WHERE node.nid = 218)
";
$result = db_query($query);
dsm($result);
The dsm is giving me an empty object. When I run the SQL directly I get back a result.
So my question would be how would you get db_query to return you all your results as an object (I don't really mind if an object or array).
(The SQL was created by looking at the query output for views.)
This is a follow up to question: Drupal Views Relationships and Arguments
I have a Person content type. It has a
node reference field of a company
which is also a content type. I then
have a content type called Project. A
project has a node reference to a
company content type. I want to list
all the projects related to a person
id (nid)id (nid)
The following works:
$query =
"
SELECT node.nid AS projectnid
FROM node node
INNER JOIN content_type_project node_data_field_project_client ON node.vid = node_data_field_project_client.vid
WHERE node_data_field_project_client.field_project_client_nid = (SELECT node_data_field_profile_company.field_profile_company_nid AS company_nid
FROM node node LEFT JOIN content_type_profile node_data_field_profile_company ON node.vid = node_data_field_profile_company.vid WHERE node.nid = 218)
";
$results = db_query($query);
while ($result = db_result($results)) {
dsm($result);
}
You need to use db_result() to get the results out. Worked this out by using http://drupal.org/node/259432#comment-846946