So I am trying to pull information about business listings from a wordpress database. The information is stored in the wp_posts table and the wp_postmeta table where all of the additional business information is listed.
The wp_postmeta table saves data like this: each piece of data has it's own row, the information is not stored as a serialized array all in one row.
Here is my database query so far:
$wpdb->get_results(
" SELECT * FROM " . $wpdb->posts .
" LEFT JOIN " . $wpdb->postmeta .
" ON " . $wpdb->posts . ".ID = " . $wpdb->postmeta . ".POST_ID" .
" WHERE " . $wpdb->posts . ".POST_TYPE = 'lv_listing' " .
" AND " . $wpdb->posts . ".POST_STATUS = 'publish' " .
" GROUP BY " . $wpdb->posts . ".ID");
Currently, each set of results gives me only one row from the wp_postmeta table, where I am expecting like 20 rows that should match the ID I am grouping by.
What am I doing wrong?
As per my understanding ,can you execute a query in the MySQL database and check if the Data is coming as per your req or not in the database .
Below is the syntax of the left outer join
SELECT column_name(s)
FROM table1
LEFT JOIN table2 ON table1.column_name = table2.column_name;
Related
I'm trying to get data from two tables: users and posts using left join.
$items = '';
$sql = "
SELECT u.id as uid
, u.name as uname
, p.id as pid
, p.date as pdate
, p.title as ptitle
, p.user as puser
FROM users u
LEFT
JOIN posts p
ON u.id = p.user
WHERE u.role = 'mod'
GROUP
BY p.title;";
$stmt = $db->query($sql);
while($row = $stmt->fetch()){
$date = strtotime($row['pdate']);
$date = date("d-m-Y", $date);
$items.= "<div class='itemp' data-id=" . $row['pid'] . " data-user='" . $row['uname'] . "'>" .
"<span class='spandate'>" . $date . "</span>" .
"<span class='spantitle'>" . $row['ptitle'] . "</span>" .
"<span class='spanuser'>" . $row['uname'] . "</span>" .
"</div>\n";
}
echo $items;
Output is ok except first row where I see the date - 1.1.1970 - but there is no any row in posts with that date. Plus - in the same row ptitle is missing.
Also, is there a better way to create this query, avoiding as keyword ?
desired output (single block):
<div class='itemp' data-id=116 data-user='JOHN SMITH'><span class='spandate'>01-12-2017</span><span class='spantitle'>BLUE SKY</span><span class='spanuser'>JOHN SMITH</span></div>
Also, is there a better way to create this query, avoiding as keyword ?
Yes (but not better in my opinion):
SELECT users.id,
users.name,
posts.id,
posts.date,
posts.title,
posts.user
FROM users
LEFT
JOIN posts
ON users.id = posts.user
WHERE users.role = 'mod'
GROUP
BY posts.title;
But as mentioned in the comments you have to modify your while loop in this case to get access to your values. But I think this is not a better way of writing this query cause it makes it harder to read.
Regarding your JOIN problem. this depends on what your result should be (I guess you only want users with posts ). So you should take a look at INNER JOIN instead of LEFT JOIN. You will get only results which also have posts entrys.
Due to the nature of LEFT JOIN all entrys on the left table (in your case users) will be used, even if they donĀ“t have an entry in the posts table.
INNER JOIN will only return results which match results in both tables.
i am trying to write a query which will help me recover class, batch, and institution details from db
so far i have managed to make the following work:
SELECT
gallery.path_url AS insimage,
r3.*
FROM
gallery
INNER JOIN (
SELECT
institution.id AS insid,
institution.ProfileImageID,
institution.`name` AS insname,
institution.Locality AS inslocality,
institution.RegistrationFee AS ins_reg_fee,
institution.IsTrail AS ins_is_trail,
institution.LatLong AS latlong,
r2., activity.`name` AS activityname
FROM
institution
INNER JOIN (
SELECT
class., count() AS batch_count,
r1.
FROM
class
INNER JOIN (
SELECT
batch.ID AS batch_id,
batch.ClassID AS class_id,
batch.LevelID AS level_id,
batch.agegroupID AS agegroup_id,
count(*) AS num_batches,
min(Price) AS min_price,
max(Price) AS max_price
FROM
batch,
batchstarttimes
WHERE
batch.ID = batchstarttimes.BatchID
AND batchstarttimes.StartTime BETWEEN '" . $sttime . "'
AND '" . $endtime . "'
GROUP BY
batch.ID
) AS r1
WHERE
r1.class_id = class.ID
GROUP BY
r1.class_id
) AS r2 ON r2.institutionid = institution.id
INNER JOIN activity ON activity.id = r2.activityid
WHERE
activity.`name` LIKE '%" . $searchterm . "%'
AND institution.Locality LIKE '%" . $locality . "%'
AND institution.StatusID = 1
AND level_id = 1
AND agegroup_id = 5
) AS r3 ON r3.ProfileImageID = gallery.ID
I am stuck when i try to add two more filters batch.LevelID and batch.agegroupID
any way i can get help or someone point me to a sql visualizr tool will be helpful.
In your WHERE clause, replace:
AND level_id = 1
AND agegroup_id = 5
with:
AND batch.LevelID = CASE WHEN " . $levelID . " = 0 THEN batch.LevelID ELSE " . $levelID . " END
AND batch.agegroupID = CASE WHEN " . $ageGroupID . " = 0 THEN batch.agegroupID ELSE " . $ageGroupID . " END
The point is to compare batch.LevelID and batch.agegroupID against themselves if you want to ignore them for the filtering (this way they'll always be true) or compare them against $levelID and $ageGroupID values for specific rows.
Also, it's not recommended to use the variables directly in the query, as it's vulnerable to SQL injections attacks. Read about prepared statements here.
I have three table:
Article:
|id|title|timestamp|......
group_tags:
|id|content_id|tags_id
tags_name:
|id|name|
I need to list article title with any tag id:
function _tags_search_($id,$type){
$DB_QUERY = mySqli::f("SELECT title FROM " . ARTICLES . " LEFT JOIN " . POSTS_TAGS . " ON " . ARTICLES . ".id = " . POSTS_TAGS . ".content_id WHERE
" .POSTS_TAGS . ".tags_id = ? AND approved = 1 ORDER BY timestamp DESC LIMIT 12", $id);
foreach($DB_QUERY as $row){
$data[] = $row;
}
return $data;
}
this worked for me and show list of article title.
But I need to show tag name for tags id in addition to list title like this:
Search result for : Linux
I have two way :
three left join method ( if true how do?)
fetch another query for show tag name.
I think three join is better and faster. how do show tags name with three join method?!
try this
SELECT title, name from
group_tags g
INNER JOIN article ON a.id = g.content_id
INNER JOIN tags_name t ON t.id = g.tags_id
Let me know if you face any issue
I have the following straightforward query which is part of a garbage collection script. The script is supposed to delete unused shopping carts. A cart is unused when it was updated more than 24 hours ago and is not attached to an order or a user.
$query = "SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`, COUNT(comm_orders.cart_id) AS `c1`, COUNT(comm_users.cart_id) AS `c2` " .
"FROM `comm_cart` " .
"LEFT JOIN `comm_orders` ON comm_cart.id=comm_orders.cart_id " .
"LEFT JOIN `comm_users` ON comm_cart.id=comm_users.cart_id " .
"GROUP BY comm_cart.id ";
"HAVING `diff`>86400 AND `c1`=0 AND `c2`=0";
The query finds too many carts: it also tags the ones that have a c1>0 or c2>0 and I can't figure out why. Any clues?
I suspect that you are joining along two different dimensions. The easy fix is to use distinct:
SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`,
COUNT(DISTINCT comm_orders.cart_id) AS `c1`, COUNT(DISTINCT comm_users.cart_id) AS `c2` " .
The better solution would be to use not exists for these two conditions:
FROM comm_carts cc
WHERE not exists (select 1 from comm_orders co where cc.id = co.cart_id )
not exists (select 1 from comm_users cu where cc.id = cu.cart_id )
You don't even need the group by, an isnull condition in the where would work wonders, of course I suggest using Gordon's suggestion of the not exists, but if you want the minimum change this would be is.
SELECT
comm_cart.id AS `cart_id`,
(UNIX_TIMESTAMP() - comm_cart.update_date) AS `diff`
FROM `comm_cart`
LEFT JOIN `comm_orders`
ON comm_cart.id=comm_orders.cart_id
LEFT JOIN `comm_users`
ON comm_cart.id=comm_users.cart_id
WHERE
comm_orders.cart_id IS NULL
AND
comm_users.cart_id IS NULL
Oh, and I've used UNIX_TIMESTAMP() instead of the PHP time function, same effect, but this avoids mixing PHP and SQL.
if you only want to get data with c1=0 and c2=0 then you need to write a where condition instead of having before group by,
$query = "SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`, COUNT(comm_orders.cart_id) AS `c1`, COUNT(comm_users.cart_id) AS `c2` " .
"FROM `comm_cart` " .
"LEFT JOIN `comm_orders` ON comm_cart.id=comm_orders.cart_id " .
"LEFT JOIN `comm_users` ON comm_cart.id=comm_users.cart_id " .
" where c1=0 and c2 =0 and diff >86400 GROUP BY comm_cart.id;
I have this code:
select count(distinct affiliate_orders_id) as count
, sum(affiliate_value) as total
, sum(affiliate_payment) as payment
from " . TABLE_AFFILIATE_SALES . " a
left join " . TABLE_ORDERS . " o on (a.affiliate_orders_id = o.orders_id)
where a.affiliate_orders_id = o.orders_id
and o.orders_status >= " . AFFILIATE_PAYMENT_ORDER_MIN_STATUS . "
";
$affiliate_sales_query= tep_db_query($affiliate_sales_raw);
$affiliate_sales= tep_db_fetch_array($affiliate_sales_query);
So, $affiliate_sales['total'] = 128000 when in fact it should be 32000 becuase there are multiple affiliate_values and affiliate_orders_id. The affilaite_values some have the same values so these cannot be distinct. affilaite_orders_id have all unique values but there are multiple rows of this and needs to be distinct. Then the affiliate_values has to sum up based on the distinct rows of affiliate_orders_id to get an accurate sum.
I'm trying to get the sum of all affiliate_values bused on how many distinct affiliate_orders_id are in the table.
Based on your update I think this will get you what you're looking for. You need to use a subQuery
SELECT COUNT(a) COUNT, SUM(av) total, SUM(ap) aptotal
FROM (
SELECT affiliate_orders_id a, affiliate_value av, SUM(affiliate_payment) AS ap
from " . TABLE_AFFILIATE_SALES . " a
left join " . TABLE_ORDERS . " o on (a.affiliate_orders_id = o.orders_id
GROUP BY affiliate_orders_id, affiliate_value)
where a.affiliate_orders_id = o.orders_id
and o.orders_status >= " . AFFILIATE_PAYMENT_ORDER_MIN_STATUS . ") a
Now this leads to a bigger question. Are you missing a join condition in your tables? Typically you shouldn't have duplicate date returned in a query, so I would suggest double checking your query is joining properly first.