MySQL - Ignore WHERE condition if key/value pair doesn't exist - php

In a Wordpress order based system I am selecting people going to an event on a certain date and location.
I also need to see if there are any order notes existing for any matching orders, which I do by selecting the meta_value where the meta_key ="_wc_acof_2".
The problem is when I add the condition to my WHERE clause the code stops returning records where that meta key/value pair doesn't exist (i.e. there are no order notes). Whereas I still need to select those records just return null or similar for the order notes.
The problem line in the WHERE clause is:
AND jn_postmeta_guestnotes.meta_key = "_wc_acof_2"
In my head I would like to write that line similar to:
AND (jn_postmeta_guestnotes.meta_key = "_wc_acof_2" OR 'there is no matching meta_key so just ignore this condition and return the record anyway')
The full query:
SELECT
CONCAT_WS(" ",wp_postmeta.meta_value,jn_postmeta_lastname.meta_value) AS Name,
wp_woocommerce_order_itemmeta.meta_value AS Adults,
jn_postmeta_guestnotes.meta_value AS Notes
FROM
wp_postmeta
LEFT JOIN
wp_postmeta AS jn_postmeta_lastname ON wp_postmeta.post_id = jn_postmeta_lastname.post_id
LEFT JOIN
wp_postmeta AS jn_postmeta_guestnotes ON wp_postmeta.post_id = jn_postmeta_guestnotes.post_id
LEFT JOIN
wp_posts ON wp_postmeta.post_id = wp_posts.ID
LEFT JOIN
wp_woocommerce_order_items ON wp_woocommerce_order_items.order_id = wp_posts.ID
LEFT JOIN
wp_woocommerce_order_itemmeta ON wp_woocommerce_order_itemmeta.order_item_id = wp_woocommerce_order_items.order_item_id
LEFT JOIN
wp_woocommerce_order_itemmeta AS jn_woocommerce_order_itemmeta_location ON wp_woocommerce_order_itemmeta.order_item_id = jn_woocommerce_order_itemmeta_location.order_item_id
LEFT JOIN
wp_woocommerce_order_itemmeta AS jn_woocommerce_order_itemmeta_date ON wp_woocommerce_order_itemmeta.order_item_id = jn_woocommerce_order_itemmeta_date.order_item_id
WHERE
1 = 1
AND wp_postmeta.meta_key = "_billing_first_name"
AND jn_postmeta_lastname.meta_key = "_billing_last_name"
AND jn_postmeta_guestnotes.meta_key = "_wc_acof_2"
AND wp_woocommerce_order_itemmeta.meta_key = "Adults"
AND jn_woocommerce_order_itemmeta_location.meta_key = "Booking Type"
AND jn_woocommerce_order_itemmeta_location.meta_value LIKE "%'.$showlocation.'%"
AND jn_woocommerce_order_itemmeta_date.meta_key = "Booking Date"
AND (jn_woocommerce_order_itemmeta_date.meta_value = "'.$showdateformata.'" OR jn_woocommerce_order_itemmeta_date.meta_value = "'.$showdateformatb.'")
AND wp_posts.post_status = "wc-completed"
GROUP BY wp_posts.ID
Any advice much appreciated!

The answer is to put the extra bit in a sub-select like so:
(SELECT wp_postmeta.meta_value FROM wp_postmeta WHERE wp_postmeta.meta_key = "_wc_acof_2" AND wp_postmeta.post_id = wp_posts.ID) AS Notes

Just put all filtering condition on the ON so the left join work. On the WHERE will remove the nulls
.....
wp_woocommerce_order_itemmeta AS jn_woocommerce_order_itemmeta_date
ON wp_woocommerce_order_itemmeta.order_item_id = jn_woocommerce_order_itemmeta_date.order_item_id
AND 1 = 1
AND wp_postmeta.meta_key = "_billing_first_name"
AND jn_postmeta_lastname.meta_key = "_billing_last_name"
AND jn_postmeta_guestnotes.meta_key = "_wc_acof_2"
AND wp_woocommerce_order_itemmeta.meta_key = "Adults"
AND jn_woocommerce_order_itemmeta_location.meta_key = "Booking Type"
AND jn_woocommerce_order_itemmeta_location.meta_value LIKE "%'.$showlocation.'%"
AND jn_woocommerce_order_itemmeta_date.meta_key = "Booking Date"
AND
(
jn_woocommerce_order_itemmeta_date.meta_value = "'.$showdateformata.'"
OR
jn_woocommerce_order_itemmeta_date.meta_value = "'.$showdateformatb.'"
)
AND wp_posts.post_status = "wc-completed"

Related

MySQL and PHP: Inner join and result

Here is a mysql request:
$requete1 = mysql_query("
SELECT a.post_id, e.meta_value
FROM wp_postmeta as b
INNER JOIN wp_postmeta AS a ON b.post_id = a.post_id
INNER JOIN wp_postmeta AS d ON b.post_id = d.post_id
INNER JOIN wp_postmeta AS e ON b.post_id = e.post_id
WHERE b.meta_key = '_show_hide_sales'
AND b.meta_value = '1'
AND d.meta_key = '_sold_sales'
AND d.meta_value != '3'
AND e.meta_key = '_sales_sort_number'
ORDER BY CAST(e.meta_value as UNSIGNED INTEGER) DESC
LIMIT ".($from-1).", ".($range+1)
);
while($resultat1 = mysql_fetch_array($requete1))
{
$res2= $resultat1['post_id']; // this one is ok
$res3= $resultat1['meta_value']; // this one is ambiguous
};
The search on the post_id ($res2) is ok as it is unambiguous.
But there are three possible meta_keys here:
The one that is related to "_show_hide_sales".
The one that is related to "_sold_sales".
The one that is related to "_sales_sort_number".
But how can I get the meta_value ($res3) that is related to the "_sales_sort_number" meta_key?
My SELECT clearly indicates that I want to retrieve the e.meta_value which should be associated to the "_sales_sort_number" meta_key but it doesn't seem to work.
Thank you for your guidance.

(P)reorder Mysqli-query results structure

I have the following query:
SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_key, wp_postmeta.meta_value
FROM wp_posts
JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE (wp_postmeta.meta_key = ? OR wp_postmeta.meta_key = ?)
AND wp_posts.post_type = ?
AND wp_posts.post_status = ?
With this query I want to loop some data about Wordpress posts (not using this query in an WP installation). I want to get 2 values:
(..WHERE (wp_postmeta.meta_key = ? OR wp_postmeta.meta_key = ?)...)
How can I match the second meta_key field result as an new column for the row with the id of the post?
I found a solution..
Tried everything with Pivot, CREATE VIEW, UNION SELECT but this is the perfect solution:
http://subharanjan.com/sql-query-to-get-post-and-its-meta_values-as-one-row-of-record-single-data-grid/

mySQL: selecting based on several keys in key/value table

I'm using Wordpress and trying to select values from one of my own tables that correspond to values in the native wp_postmeta table.
My table is called "wellwishertable" and I would like to find all the ID's (so I can count them) from the wellwisher table where...
1) The wellwishertable 'associatedID' field is in wp_postmeta post_id
2) The wellwishertable 'associatedAuthorID' is the same as a $userID variable
3) The wellwishertable 'permission' is pending
4) The wp_postmeta meta_key 'status' is NOT equal to meta_value 'open'
5) The wp_postmeta meta_key 'freeze' is NOT equal to meta_value 'frozen'
I've got this far...
"SELECT DISTINCT wellwisher.ID FROM wellwishertable wellwisher
INNER JOIN wp_postmeta ON (wellwisher.associatedID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_postmeta.post_id = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_postmeta.post_id = mt2.post_id)
WHERE wellwisher.associatedAuthorID=".$userID."
AND wellwisher.permission ='pending'
AND ( (mt1.meta_key = 'status' AND mt1.meta_value != 'open') AND
(mt2.meta_key = 'freeze' AND mt2.meta_value != 'frozen') );
This seems to be 'nearly' working except it doesn't count records that don't have a "freeze" meta_key in the wp_postmeta table. I want it to count any record that isn't "frozen" regardless of whether it exists or not (as long as 'status' isn't 'open').
Could someone point me in the right direction?
Use LEFT JOIN instead of INNER JOIN on mt2, as INNER JOIN will only return results that have an entry there.
In order to avoid requiring mt2.meta_key to always have to equal freeze, move that condition up to the ON clause in your join.
You could also consider using COUNT directly in your query rather than figuring it out later:
"SELECT COUNT(DISTINCT wellwisher.ID) FROM wellwishertable wellwisher
INNER JOIN wp_postmeta ON (wellwisher.associatedID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_postmeta.post_id = mt1.post_id)
LEFT JOIN wp_postmeta AS mt2 ON (wp_postmeta.post_id = mt2.post_id)
AND mt2.meta_key = 'freeze'
WHERE wellwisher.associatedAuthorID=".$userID."
AND wellwisher.permission ='pending'
AND ( (mt1.meta_key = 'status' AND mt1.meta_value != 'open') AND
(mt2.meta_value != 'frozen') );
IMPORTANT:
Dumping your $userID directly into your query string could be a big security issue. Please consider using parameterized queries.

WordPress Query get posts based on custom table

I have some regular WordPress posts that I need to get from the database by parent category, and order by the results of a custom table in the database that I have made.
The parent category that I want to retrieve posts for (including children) is called explorer with the id of 29.
The custom table is called wp_upvotes. in this table there are a few columns, but the only columns that we care about would probably be id and postID. I want to order the wp_posts by the number of rows that has the postID equal to the wp_post.ID, and if there are no rows in that table for the other posts, then they should be ordered by date at the end. I want the most number of upvotes to the least number of upvotes by date.
The query I have tried is this (it returns only the first post, not all of them):
$catIDs = array(29,30,31,32);
SELECT wp_posts.*, COUNT(wp_upvotes.id) AS upvotes FROM wp_posts
LEFT JOIN wp_upvotes ON (wp_posts.ID = wp_upvotes.postID)
INNER JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy
ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
AND wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.term_id IN (" . implode(',', $catIDs) . "))
AND wp_posts.post_status = 'publish'
ORDER BY upvotes DESC, wp_posts.post_date DESC
When I remove the LEFT JOIN for the wp_upvotes table it returns all of the correct posts.. Why is it only returning one row when I am using a LEFT JOIN?
SELECT wp_posts.* FROM wp_posts
INNER JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy
ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
AND wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.term_id IN (" . implode(',', $catIDs) . "))
AND wp_posts.post_status = 'publish'
ORDER BY wp_posts.post_date DESC
Looks like the main factor was to use ORDER BY wp_posts.ID for whatever reason to make it show all of the rows instead of just one.. Odd but here's my final code to do what I wanted to do above:
SELECT wp_posts.*, COUNT(wp_upvotes.id) AS upvotes FROM wp_posts
INNER JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy
ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
AND wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.parent = 29)
LEFT JOIN wp_upvotes ON (wp_posts.ID = wp_upvotes.postID)
WHERE wp_posts.post_status = 'publish'
GROUP BY wp_posts.ID
ORDER BY upvotes DESC, wp_posts.post_date DESC

Getting Multiple Values from a table column into a repeating row

I'm using Wordpress and I have to figure out how to get multiple values out of the same column and turn them into variables.
The last step is I just want the data to display in a table like so:
Bob Company1 <br>
Alex Company2
Instead I get either Bob Alex Company1 Company 2 or
Bob <br>
Alex<br>
Company1<br>
Company2
Here's two different versions I'm working with:
$sql = "SELECT meta_value as guest from wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE post_type='guests' AND meta_key='guest_name' UNION SELECT meta_value as company from wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE post_type='guests' AND meta_key='guests_company'";
$result = mysql_query($sql);
$NumberOfResults=mysql_num_rows($result);
if (mysql_num_rows($result) == 0) {
echo "No Guests yet... stay tuned!";
exit;
}
while(list($guest,$company)= mysql_fetch_row($result))
{
echo "<table><tr><td>".$guest."</td><td>".$company."</td></tr></table>";
}
or
$sql = mysql_query("SELECT meta_value as guest from wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE post_type='guests' AND meta_key='guest_name' LIMIT 2 UNION SELECT meta_value as company from wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE post_type='guests' AND meta_key='guests_company'");
$i = 1;
while ($get = mysql_fetch_array($sql))
{
echo '<table><tr><td>'.$get["guest"].'</td><td>'.$get["company"].'</td></tr></table>';
$i++;
}
ANY HELP would be so appreciated!!! thanks!
Edit: In case anybody in the future wants to create their own widget using advanced custom fields in Wordpress, here's the final product more or less:
$sql = "SELECT p.ID AS post_id, g.meta_value as guest, c.meta_value as company, d.meta_value as date
FROM wp_posts p
JOIN wp_postmeta g ON g.post_id = p.id AND g.meta_key = 'guest_name'
JOIN wp_postmeta c ON c.post_id = p.id AND c.meta_key = 'guests_company'
JOIN wp_postmeta d ON d.post_id = p.id AND d.meta_key = 'show_date'
WHERE p.post_status = 'publish'
ORDER by d.meta_value DESC";
$query = mysql_query($sql);
echo '<table><tr><th>Guest</th><th>Company</th><th>Show Date</th></tr>';
while ($get = mysql_fetch_array($query)) {$newDate = date("m-d-Y", strtotime($get["date"]));
echo '<tr><td>'.$get["guest"].'</td><td>'.$get["company"].'</td><td>'.$newDate.'</td></tr>';
}
echo '</table>';
Really appreciated doublesharp's help on this.
If I understand your question correctly, you have to write the code to display table like this:
echo '<table>';
while ($get = mysql_fetch_array($sql))
{
echo '<tr><td>'.$get["guest"].'</td><td>'.$get["company"].'</td></tr>';
}
echo '</table>';
If the postmeta values are attached to different posts as indicated by the different 'post_type' values in your query, then you will need some other identifying information to link them together. If there is a single post_id that has both a guest_name and guest_company meta_value then you can join it twice to get the results. Using a UNION will always result in them coming back in different rows.
// Join the postmeta table to posts twice, once for each meta_key.
$sql = <<<SQL
SELECT p.ID AS post_id, g.meta_value as guest, c.meta_value as company
FROM wp_posts p
JOIN wp_postmeta g ON g.post_id = p.id AND g.meta_key = 'guest_name'
JOIN wp_postmeta c ON c.post_id = p.id AND c.meta_key = 'guests_company'
WHERE p.post_status = 'publish'
SQL;
// Execute the query
$query = mysql_query($sql);
// Start your table for output
echo '<table>';
while ($get = mysql_fetch_array($query)) {
// Write the output of each row
echo '<tr><td>'.$get["guest"].'</td><td>'.$get["company"].'</td></tr>';
}
// Close the table
echo '</table>';
If this is inside Wordpress, I would recommend using the $wpdb object for your query.

Categories