SQL group inner join cannot get all results - php

I really trying to get this SQL to work. Im no expert so really cant figure this out.
$sqlquery = " SELECT
s.searchword AS searchword,
s.id AS id,
COUNT( c.id ) AS searchresult,
s.region AS region
FROM search_words AS s
INNER JOIN company_data AS c ON
c.branch_text LIKE CONCAT( '%', s.searchword, '%' )
GROUP BY 1 ORDER BY s.date DESC";
This gives me:
Array
(
[0] => Array
(
[searchword] => WHOLESALE
[searchid] => 427
[searchresult] => 98
[region] => stockholm
)
[1] => Array
(
[searchword] => cars
[searchid] => 426
[searchresult] => 26
[region] =>
)
[2] => Array
(
[searchword] => Retail
[searchid] => 342
[searchresult] => 41
[region] => stockholm
)
[3] => Array
(
[searchword] => Springs
[searchid] => 339
[searchresult] => 4
[region] => stockholm
)
[4] => Array
(
[searchword] => Leasing
[searchid] => 343
[searchresult] => 2
[region] => stockholm
)
[5] => Array
(
[searchword] => Food
[searchid] => 340
[searchresult] => 37
[region] => stockholm
)
)
But, it does not give me any of the other results where there are no searchhits, would retur something like [searchresult] => 0. Meaning they do not group as I wish, because there are no such searchwords within the company_data table.
How can I fix this, please help :(
EDIT:
Here is the full code:
public function getUserSearches()
{
$sqlquery = " SELECT
s.searchword AS searchword,
s.id AS id,
s.userId AS userid,
COUNT( c.id ) AS searchresult,
s.region AS region
FROM search_words AS s
INNER JOIN company_data AS c ON
c.branch_text LIKE CONCAT( '%', s.searchword, '%' )
GROUP BY 1 ORDER BY s.date DESC";
// IS THERE ANYTHING WRONG HERE?? LIKE IT DOES NOT MATCH AGAINST THE USER?
$result = $this->dbh->query($sqlquery, array(":userId" => $this->user_id));
$arr = array();
foreach ($result as $item) {
array_push($arr, array('searchword' => $item['searchword'], 'searchid' => $item['id'],
'searchresult' => $item['searchresult'], 'userid' => $item['userid'],
'region' => $item['region']));
}
return json_encode($arr);
return print_r($arr);
}

Use LEFT JOIN so that any row that doesn't match the search criteria in the join condition will come with null, therefore count will be 0. Something like this:
SELECT
s.searchword AS searchword,
s.id AS id,
s.region AS region,
COUNT(COALESCE(c.id, 0)) AS searchresult
FROM search_words AS s
LEFT JOIN company_data AS c
ON c.branch_text LIKE CONCAT( '%', s.searchword, '%' )
GROUP BY s.searchword, s.id, s.region
ORDER BY s.date DESC;
See this for more details about the SQL Join types.

You need a LEFT JOIN, instead of an INNER JOIN. However, there are other simplifications you can make as well:
SELECT s.searchword, s.id, COUNT( c.id ) AS searchresult, s.region
FROM search_words s INNER JOIN
company_data c
ON c.branch_text LIKE CONCAT('%', s.searchword, '%')
GROUP BY 1
ORDER BY s.date DESC
For instance, you don't need column aliases when you are not changing the column name. You are only aggregating on searchword; I assume this is unique in search_words. Otherwise, s.id, s.region. and s.date would have indeterminate values.
The use of LIKE for the JOIN affects performance. If you only have a small amount of data, this is fine. Otherwise, you might want to think about other data structures.

I think what you want is perhaps this:
public function getUserSearches()
{
$sqlquery = " SELECT
s.searchword AS searchword,
s.id AS id,
s.userId AS userid,
COUNT( c.id ) AS searchresult,
s.region AS region
FROM search_words AS s
WHERE s.userId='"+$this->userid+"'
LEFT JOIN company_data AS c ON
c.branch_text LIKE CONCAT( '%', s.searchword, '%' )
GROUP BY 1 ORDER BY s.date DESC";
// IS THERE ANYTHING WRONG HERE?? LIKE IT DOES NOT MATCH AGAINST THE USER?
$result = $this->dbh->query($sqlquery);
$arr = array();
foreach ($result as $item) {
array_push($arr, array('searchword' => $item['searchword'], 'searchid' => $item['id'],
'searchresult' => $item['searchresult'], 'userid' => $item['userid'],
'region' => $item['region']));
}
return json_encode($arr);
return print_r($arr);
}

Related

Filtering a MySQL query with multiple conditions

I have my output array named "Feed Items" (fi):
(
[0] => Array
(
[reg] => 2015-08-03 13:39:00
[id] => fd7ec4107d16b07c1a13cbdd386af8d2cb05ffca
[user_id] => de5fd44db1760b006b1909cf1db11a78b38e455c
[img] => edee88e88cf6e17732e393b5433cfd894662902e
[type] => new_join_ambition
)
)
I generate an array named "RemovedFeedItems" (rfi) that has the following structure:
(
[0] => Array
(
[object_id] => fd7ec4107d16b07c1a13cbdd386af8d2cb05ffca
[postee_id] => de5fd44db1760b006b1909cf1db11a78b38e455c
[type] => new_join_ambition
)
)
My mission is to not get the records that have the following condition:
ri.id == rfi.object_id && ri.user_id == rfi.postee_id && ri.type == rfi.type
The query that I use to get the Feed Items array is:
SELECT
i.registered AS reg,
a.id,
u.id AS user_id,
ui.image_id AS img,
'new_join_ambition' AS type,
FROM x_ambition_invites i
LEFT JOIN x_user u
ON i.to = u.id
LEFT JOIN x_user_images ui
ON u.id = ui.user_id
LEFT JOIN x_ambitions a
ON i.ambition_id = a.id
WHERE a.registered
BETWEEN '2014-07-21 14:25:03' AND '2015-08-05 12:04:41'
AND i.to != '8fa7a1679560876eaf2f8060abd916b692c719dc'
AND i.to IN ('de5fd44db1760b006b1909cf1db11a78b38e455c')
How can I adapt my query to implement the condition to remove the stated record from the FeedItems Array?
Thanks in advance.
Try with an inline table:
SELECT ... FROM ... WHERE (a,b,c) NOT IN (SELECT a1, b1, c1 UNION SELECT a2, b2, c2 UNION SELECT...)
The drawback is that you'll have to build a large query string. :-(

UNION in MYSQL and merge columns

I am fetching data from two tables in mysql. I have query like this:
SELECT SUM(IF(debit IS NULL, 0, debit)) - SUM(IF(credit IS NULL, 0, credit)) as amount, th.country_id, cl.currency_name
FROM account_treasury_hq th
LEFT JOIN system_country_list cl ON cl.country_id=th.country_id
WHERE th.company_id='$company_id'
GROUP BY th.country_id
UNION
SELECT SUM(CASE WHEN ce_type = 'IN' or ce_type is NULL then payment_amount
WHEN ce_type = 'OUT' then - payment_amount
END) as amount,
source_country_id as country_id, cl.currency_name
FROM customer_payment_options cpo
LEFT JOIN system_country_list cl ON cl.country_id=cpo.source_country_id
WHERE cpo.company_id='$company_id'
GROUP BY cpo.source_country_id
Result
Array
(
[0] => Array
(
[amount] => -345
[country_id] => 40
[currency_name] => Canadian dollar
)
[1] => Array
(
[amount] => 93
[country_id] => 210
[currency_name] => Sri Lankan rupee
)
[2] => Array
(
[amount] => 46.5
[country_id] => 236
[currency_name] => United States dollar
)
[3] => Array
(
[amount] => 916249.8999999999
[country_id] => 40
[currency_name] => Canadian dollar
)
[4] => Array
(
[amount] => -6670.1
[country_id] => 210
[currency_name] => Sri Lankan rupee
)
[5] => Array
(
[amount] => 2017.67
[country_id] => 236
[currency_name] => United States dollar
)
)
In the result array, you can see the same country_id. I want to merge those same country id with 1. It means, there should only be each amount information for each country_id.
(amount should be added by adding multiple countries)
Is there any way to do it in PHP or mysql itself?
Thanks for any kind of help.
Required Result
Array
(
[0] => Array
(
[amount] => 915904.89
[country_id] => 40
[currency_name] => Canadian dollar
)
[1] => Array
(
[amount] => -6577.1
[country_id] => 210
[currency_name] => Sri Lankan rupee
)
[2] => Array
(
[amount] => 2064.17
[country_id] => 236
[currency_name] => United States dollar
)
)
just select it all in an outer query sum the amount and group by country_id
SELECT
SUM(amount) country_id, currency_name
FROM
( SELECT
SUM(IF(debit IS NULL, 0, debit)) - SUM(IF(credit IS NULL, 0, credit)) as amount,
th.country_id,
cl.currency_name
FROM account_treasury_hq th
LEFT JOIN system_country_list cl ON cl.country_id=th.country_id
WHERE th.company_id='$company_id'
GROUP BY th.country_id
UNION
SELECT
SUM(CASE
WHEN ce_type = 'IN' or ce_type is NULL then payment_amount
WHEN ce_type = 'OUT' then - payment_amount
END
) as amount,
source_country_id as country_id,
cl.currency_name
FROM customer_payment_options cpo
LEFT JOIN system_country_list cl ON cl.country_id=cpo.source_country_id
WHERE cpo.company_id='$company_id'
GROUP BY cpo.source_country_id
) t
GROUP BY country_id
You're doing a union, with grouping in the individual subquery. Each subquery in a union has NO awareness of what the other parallel queries are doing. Each query's group by will apply only to that ONE query.
You'd need to do the heavy duty work in a wrapper query, e.g.
SELECT SUM(.....)
FROM (
SELECT th.country_id AS country_id, etc...
UNION ALL
SELECT source_country AS country_id, etc...
) AS foo
GROUP BY country_id
e.g. do all the grouping and "math" in the outer query, and the inner queries simply retrieve all the records you do want grouped together.
Didn't test this (would need a sqlfiddle to play with) but you'd want to aggregate them in the query. Something like this (you'll want to tweak the group by and select for your needs):
SELECT SUM( x.amount ), x.country_id, x.currency_name
FROM
(
SELECT SUM(IF(debit IS NULL, 0, debit)) - SUM(IF(credit IS NULL, 0, credit)) as amount, th.country_id, cl.currency_name
FROM account_treasury_hq th
LEFT JOIN system_country_list cl ON cl.country_id=th.country_id
WHERE th.company_id='$company_id'
GROUP BY th.country_id
UNION
SELECT SUM(CASE WHEN ce_type = 'IN' or ce_type is NULL then payment_amount
WHEN ce_type = 'OUT' then - payment_amount
END) as amount,
source_country_id as country_id, cl.currency_name
FROM customer_payment_options cpo
LEFT JOIN system_country_list cl ON cl.country_id=cpo.source_country_id
WHERE cpo.company_id='$company_id'
GROUP BY cpo.source_country_id
) AS x
GROUP BY x.amount, x.country_id, x.currency_name

How to select Distinct on inner join?

Can help me, I have something problem about query select distinct, :
My table
table_pemesan
id_pms
table_pesan
no_psn
id_pms
table_dpesan
no_psn
My query mysql
select pm.id_pms,
pm.nama,
pm.date_create,
ps.no_psn,
ps.status,
dps.no_dpsn
FROM pemesan as pm
INNER JOIN pesan ps on ps.id_pms=pm.id_pms
INNER JOIN dpesan dps on dps.no_psn=ps.no_psn
ORDER BY pm.id_pms ASC
//output
Array
(
[0] => Array
(
[id_pms] => 1
[nama] => Isnan
[date_create] => 2014-05-28 23:54:54
[no_psn] => 1
[status] => sedang diproses
[no_dpsn] => 1
)
[1] => Array
(
[id_pms] => 1
[nama] => Isnan
[date_create] => 2014-05-28 23:54:54
[no_psn] => 1
[status] => sedang diproses
[no_dpsn] => 2
)
)
the array index 0 & 1 the same data, and my question how to distinct the query? thanks b4, sorry my english not good..
Try to use this query:-
SELECT DISTINCT pm.id_pms, pm.nama, pm.date_create, ps.no_psn, ps.status, dps.no_dpsn
FROM pemesan as pm
INNER JOIN pesan ps on ps.id_pms=pm.id_pms
INNER JOIN dpesan dps on dps.no_psn=ps.no_psn
ORDER BY pm.id_pms ASC

Foreach not displaying the Results

Hi am using the following Query need to get the order_id and product_id from this query ,
well when I run the query in phpmyadmin results are displayed.
global $wpdb;
$sql = "SELECT oi.order_id, p.ID as product_id, p.post_title, p.post_author as seller_id,
oim2.meta_value as order_total, terms.name as order_status
FROM {$wpdb->prefix}woocommerce_order_items oi
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oim.order_item_id = oi.order_item_id
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim2 ON oim2.order_item_id = oi.order_item_id
LEFT JOIN $wpdb->posts p ON oim.meta_value = p.ID
LEFT JOIN {$wpdb->term_relationships} rel ON oi.order_id = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} tax ON rel.term_taxonomy_id = tax.term_taxonomy_id
LEFT JOIN {$wpdb->terms} terms ON tax.term_id = terms.term_id
WHERE
oim.meta_key = '_product_id' AND
oim2.meta_key = '_line_total'
GROUP BY oi.order_id";
$orders = $wpdb->get_results( $sql );
if ( $orders ) {
foreach ($orders as $order) {
$result=customFunction(**$order->order_id,$order->product_id,$order->seller_id**);
}
the problem is $order->order_id and $order->product_id value is not getting passed to the function but only $order->seller_id is getting passed. But in phpmyadmin the values are present for all the three variables.
tried
echo $orders[product_id] ;
echo $orders[order_id] ;
echo $orders[seller_id];
Hut only echo $orders[seller_id]; shows the value.
Here is the array structure:
Array (
[0] => stdClass Object (
[order_id] => 2774
[product_id] => 2531
[post_title] => Klassic Koalas Mug
[seller_id] => 3
[order_total] => 12
[order_status] => cancelled
)
[1] => stdClass Object (
[order_id] => 2869
[product_id] => 2622
[post_title] => Mug, Aqua
[seller_id] => 1
[order_total] => 1
[order_status] => on-hold
)
I'll put this in a comment but I don't have enough reputation. Do:
var_dump($orders)
and see what's inside. Maybe they are fetched as 'oi.order_id'.
Unsure about product_id, but it seems that order_id is not showing up because you are not setting and alias for order_id. So take this:
SELECT oi.order_id,
And change it to this
SELECT oi.order_id as order_id,
Past that do a dump of $orders to see the overall structure like this:
echo '<pre>';
print_r($orders);
echo '</pre>';
Lets debug this first, var_dump is your friend! try :
$orders = $wpdb->get_results( $sql );
var_dump($orders); die();
Now, after adding the var_dump, check the result, if order_id and product_id still don't have result, might be there is a DB issue? Then you have to fix your DB first.

Output concated value from mysql query

I am trying to output a concated value from my query but am having some issues.
Here is my query:
$result = mysql_query(
"SELECT c.company, n.nid, n.createdOn, CONCAT_WS(' ',c2.fname,c2.lname), CONCAT_WS(' ',c3.fname,c3.lname), n.urgent, n.description
FROM notes n
INNER JOIN Positions p ON FIND_IN_SET(p.id, n.forDepts) > 0
LEFT JOIN companies c ON c.userid = n.clientId
LEFT JOIN companies c2 ON c2.userid = n.createdBy
LEFT JOIN companies c3 ON c3.userid = n.claimedBy
GROUP BY n.nid
LIMIT 0,100"
);
My array is printing like so:
Array ( [0] => Honda of Kirkland [company] => Honda of Kirkland [1] => 1 [nid] => 1 [2] => 2009-09-28 21:33:15 [createdOn] => 2009-09-28 21:33:15 [3] => [CONCAT_WS(' ',c2.fname,c2.lname)] => [4] => [CONCAT_WS(' ',c3.fname,c3.lname)] => [5] => 0 [urgent] => 0 [6] => Milestones [description] => Milestones )
I am trying it like this, but it does not work:
while ($row = mysql_fetch_array($result)) {
$created_by = $row[3];
}

Categories