SQL LEFT JOIN with possible join condition duplicate match - mysql

Here is my query so far:
SELECT
b.cs_bidding_id, b.cs_bidding_user_id,
floor(AVG(u.cs_rating)) AS cs_user_rating
FROM cs_biddings b LEFT JOIN
cs_user_ratings u ON u.cs_user_rated_id = b.cs_bidding_user_id
I would like to get the avg rating of the user's per bidding post.
However this does not work for multiple biddings because whenever the join condition is satisfied, it wont let me fetch other avg rating for other biddings that shares the same bidding_user_id
desired result:
Unsummarized Query:
SELECT
b.cs_bidding_id,
b.cs_bidding_title,
b.cs_bidding_details,
b.cs_bidding_user_id,
b.cs_bidding_permalink,
b.cs_bidding_added,
b.cs_bidding_picture,
b.cs_bidding_status,
b.cs_bidding_location,
floor(AVG(u.cs_rating)) AS cs_owner_rating
FROM cs_biddings b LEFT JOIN
cs_user_ratings u ON u.cs_user_rated_id = b.cs_bidding_user_id

Your query is malformed. It is an aggregation query (because of the AVG()) but the SELECT columns are inconsistent with the aggregation columns (well, there are none of those).
Fixing the group by might fix your problem:
SELECT b.cs_bidding_id, b.cs_bidding_user_id,
floor(AVG(u.cs_rating)) AS cs_user_rating
FROM cs_biddings b LEFT JOIN
cs_user_ratings u
ON u.cs_user_rated_id = b.cs_bidding_user_id
GROUP BY b.cs_bidding_id, b.cs_bidding_user_id;
I'm not sure if you want both columns in the GROUP BY (and the result set). However, without sample data and desired results, it is unclear what you actually intend.

Related

MySQL Left Outer Join & Count - 'Where'?

I have a relatively simple query that returns a user profile, together with 2 counts related to that user (stream events & inventory);
SELECT u.*, r.regionName, COUNT(i.fmid) AS invcount, COUNT(s.fmid) AS streamcount
FROM fm_users u
JOIN fm_regions r
ON u.region=r.regionid
LEFT OUTER JOIN fm_inventory i
ON u.fmid=i.fmid
LEFT OUTER JOIN fm_stream s
ON u.fmid=s.fmid
WHERE u.username='sampleuser'
Both the inventory & stream values could be zero, hence using a left outer join.
However, the values for both currently return numbers for all users, not the specific user (always identified as integer 'fmid' in each table). This is obviously because the query doesn't specify a 'where' for either count - but I'm not sure where. If I change the last part to this;
WHERE u.username='sampleuser' AND s.fmid=u.fmid AND i.fmid=u.fmid
GROUP BY u.fmid
It still returns incorrect numbers, albeit 'different' numbers depending on the search criteria - and the name number for both invcount and streamcount.
Your query cross joins the fm_inventory and fm_stream tables for each user. For example if a specific user has 2 matching fm_inventory rows, and fm_stream also has two, the result will have 4 (=2 x 2) rows and each will be counted in both COUNT() functions.
The way to accomplish what you are doing is to use correlated subselects for the counts.
SELECT u.*, r.regionName,
(select COUNT(*) from fm_inventory i
where i.fmid = u.fmid) AS invcount,
(select COUNT(*) from fm_stream s
where s.fmid = u.fmid) AS streamcount
FROM fm_users u
JOIN fm_regions r
ON u.region=r.regionid
WHERE u.username='sampleuser'
This allows the counts to be independent of each other. This works even if more than just one user is selected. In that case you need a group by clause, but otherwise it is the same syntax.
When you mix normal columns with aggregates, include all normal columns in the GROUP BY. In this particular case, you are missing the r.regionName in the GROUP BY.
See longer explanation.

How do I sum [add] multiple columns from joined tables

I need to write a query that joins several tables and totals several columns in different tables & can't seem to figure out how to do it:
here are the tables:
The result I am trying to get is a result with the contract budgets for a particular budget name added: i.e. [this does not work but gives an idea]
select c.contract_budget_f1, c.contract_budget_f2, cb.budget_type_id, c.id, sum(cb.budget_f1) as bf1, sum(cb.budget_f2) as bf2
from `flow_contract` c
left join `flow_contract_budget` cb on cb.contract_id = c.id
where c.program_id = '69'
group by cb.budget_type_id
with the whole result set looking like:
[budget_type_id]
[contract_budget_f1]
[contract_budget_f2]
[bf1]
[bf2]
where it will return 3 rows with the budgets for each budget type added
How can I do this, is it even possible?
Here are links to the tables - sorry, didn't realize you couldn't click on them...
http://media.bigblockstudios.ca/stack/program-name.gif
http://media.bigblockstudios.ca/stack/contract-budget.gif
http://media.bigblockstudios.ca/stack/contracts.gif
UPDATE
I got it working like this:
select c.id, c.program_id, c.contract_budget_f1, c.contract_budget_f2, cb.budget_f1, cb.budget_f2, cb.budget_type_id, c.id,
sum(cb.budget_f1) as bf1, sum(cb.budget_f2) as bf2
from `flow_contract` c
left join `flow_contract_budget` cb on cb.contract_id = c.id
where c.program_id = '".$formfields['program_id']."'
group by cb.budget_type_id
order by cb.budget_type_id
I think what you want is:
group by cb.budget_type_id, cb.contract_id
Or the other way around. Could you make an sql fiddle?
Short Answer: subquery
Try this:
Start with a subquery.
Write a query that produces the column values that you want to sum. This is now the subquery.
Write an outter query that sums the desired columns in the inner query.
After you get it working, review it to see if you can optimize out the subquery and just have one query.

SQL join query - join instead of inline query

I would like to use join instead of inline queries but the one I was able to make is giving wrong values.
Please check this link - http://www.sqlfiddle.com/#!2/57cad/9
It has 2 individual queries which give correct values and a join query which gives an incorrect result.
Can someone please help...
Answer shown here: SQLFiddle
Your queries could be improved upon in a few areas which make their JOINing a little more obvious.
In your first query, a better version has the the GROUP BY clause's columns listed in the SELECT clause and your HAVING clause (while working) becomes the WHERE clause (IMO: The best practice is to use aggregate function only in the HAVING clause:)
SELECT usercode, ROUND(coalesce(sum(paymentamount)*0.99,0),2) AS payment
FROM accountpayments
WHERE usercode = 21
GROUP BY usercode;
Your second query can be rewritten as a JOIN (vs. the subquery)
SELECT campaigns.usercode, ROUND(coalesce(sum(lmc_cds.total_spending),0),2) AS total_spending
FROM logsmaincontrols_campaigns_daily_stats AS lmc_cds
JOIN campaigns
ON campaigns.campcode = lmc_cds.campcode
WHERE campaigns.usercode = 21;
Since the queries don't share any tables, I decided to JOIN the queries to each other as derived tables using the usercode as the JOINing column.
SELECT t1.usercode, t1.payment, t2.total_spending
FROM (SELECT usercode, ROUND(coalesce(sum(paymentamount)*0.99,0),2) AS payment
FROM accountpayments
WHERE usercode = 21
GROUP BY usercode) AS t1
JOIN (SELECT campaigns.usercode, ROUND(coalesce(sum(lmc_cds.total_spending),0),2) AS total_spending
FROM logsmaincontrols_campaigns_daily_stats AS lmc_cds
JOIN campaigns
ON campaigns.campcode = lmc_cds.campcode
WHERE campaigns.usercode = 21) AS t2
ON t1.usercode = t2.usercode;

sql/Mysql: What is the best method to complete this query

I had most of this query worked about except two things, large things, one, as soon as I add the forth table [departments_tbl]into the query, I get about 8K rows returned when I should only have about 100.
See the attached schema, no the checkmarks, these are the fields I want returned.
This won't help, but here is just one of the queries that I almost had working, until the [department_tbl was added to the mix]
SELECT _n_cust_entity_storeid_15.entity_id,
_n_cust_entity_storeid_15.email,
customer_group.customer_group_code,
departments.`name`,
departments.manager,
_n_cust_rpt_copy.first_name,
_n_cust_rpt_copy.last_name,
_n_cust_rpt_copy.last_login_date,
_n_cust_rpt_copy.billing_address,
_n_cust_rpt_copy.billing_city,
_n_cust_rpt_copy.billing_state,
_n_cust_rpt_copy.billing_zip
FROM _n_cust_entity_storeid_15 INNER JOIN customer_group ON _n_cust_entity_storeid_15.group_id = customer_group.customer_group_id
INNER JOIN departments ON _n_cust_entity_storeid_15.store_id = departments.store_id,
_n_cust_rpt_copy
ORDER BY _n_cust_rpt_copy.last_name ASC
I've tried subqueries, joins, but just can't get it to work.
Any help would be greatly appreciated.
Schema Please note that entity_id and cust_id fields would the be links between the _ncust_rpt_copy table and the _n_cust_entity_storeid_15 tbl
You have a cross join to the last table, _n_cust_rpt_copy:
SELECT _n_cust_entity_storeid_15.entity_id,
_n_cust_entity_storeid_15.email,
customer_group.customer_group_code,
departments.`name`,
departments.manager,
_n_cust_rpt_copy.first_name,
_n_cust_rpt_copy.last_name,
_n_cust_rpt_copy.last_login_date,
_n_cust_rpt_copy.billing_address,
_n_cust_rpt_copy.billing_city,
_n_cust_rpt_copy.billing_state,
_n_cust_rpt_copy.billing_zip
FROM _n_cust_entity_storeid_15 INNER JOIN
customer_group
ON _n_cust_entity_storeid_15.group_id = customer_group.customer_group_id INNER JOIN
departments
ON _n_cust_entity_storeid_15.store_id = departments.store_id join
_n_cust_rpt_copy
ON ???
ORDER BY _n_cust_rpt_copy.last_name ASC;
It is not obvious to me what the right join conditions are, but there must be something.
I might guess they it at least includes the department:
_n_cust_rpt_copy
ON _n_cust_rpt_copy.department_name = departments.name and

How to refine this sql query with a LEFT JOIN?

I have a problem with the following SQL Query. As you can see, I join some tables (candidate_basic,candidate_lang,province_of_candidate,province,degree_of_candidate), and then I join the result with another table "professional_experience_basic" but, the query return several instances (example: it returns two instances for id_candidate_basic=55, or it returns three instances of id_candidate_basic=59).
My problem is that I only want that the query return 1 instance per id_candidate_basic. That is, the instance with attribute "main_job" with value 1, and if this is not possible, just a null.
I tried to put AND professional_experience_basic.main_job=1 inside the WHERE clause, but, it remove the instances with main_job=null.
I feel that I'm close to the final result but I have spent lots of minutes in this last effort. Does anyone know the solution?
Thanks in advance.
The Query:
SELECT DISTINCT
candidate_basic.id_candidate_basic,
candidate_lang.town,
province.name,
degree_of_candidate.id_degree_of_candidate,professional_experience_basic.main_job
FROM (((((candidate_basic
INNER JOIN candidate_lang
ON candidate_lang.id_candidate_basic=candidate_basic.id_candidate_basic)
INNER JOIN province_of_candidate
ON province_of_candidate.id_candidate_basic=candidate_basic.id_candidate_basic)
INNER JOIN province
ON province.id_province=province_of_candidate.id_province)
INNER JOIN degree_of_candidate
ON degree_of_candidate.id_candidate_basic=candidate_basic.id_candidate_basic)
LEFT JOIN professional_experience_basic
ON professional_experience_basic.candidate_id=candidate_basic.id_candidate_basic)
WHERE candidate_basic.candidate_state=2
AND degree_of_candidate.is_main_degree
AND candidate_lang.id_website_lang=1
The current result:
The result I want:
Change professional_experience_basic.main_job to max(professional_experience_basic.main_job) in the column list, then:
GROUP BY candidate_basic.id_candidate_basic, candidate_lang.town,
province.name, degree_of_candidate.id_degree_of_candidate
First Group your Result
... AND candidate_lang.id_website_lang=1
GROUP BY
candidate_basic.id_candidate_basic,
candidate_lang.town,
province.name,
degree_of_candidate.id_degree_of_candidate
And i think you want the max of main_job, but i dont know.
change select to:
SELECT DISTINCT
candidate_basic.id_candidate_basic,
candidate_lang.town,
province.name,
degree_of_candidate.id_degree_of_candidate,MAX(professional_experience_basic.main_job)
It seems like you want the max here, but i dont know