MySQL left join with different parameter as group by gives different results - mysql

Here is the first statement:
SELECT * FROM (
SELECT E.EMP_NAME,O.NAME AS DEPTNAME
FROM M_EMPLOYEE E
LEFT JOIN M_USERS U ON U.USER_ID=E.USER_ID
LEFT JOIN M_ORGANIZATION O ON U.DEPT_ID=O.ORG_ID
GROUP BY E.USER_ID)T WHERE T.EMP_NAME='lm';
Here is the result:
EMP_NAME | DEPTNAME
lm | null
Here is the second statement:
SELECT * FROM (
SELECT E.EMP_NAME,O.NAME AS DEPTNAME
FROM M_EMPLOYEE E
LEFT JOIN M_USERS U ON U.USER_ID=E.USER_ID
LEFT JOIN M_ORGANIZATION O ON U.DEPT_ID=O.ORG_ID
GROUP BY U.USER_ID )T WHERE T.EMP_NAME='lm';
Here is the result:
EMP_NAME | DEPTNAME
lm | qitan
Question: Why the two results are different?

From MySQL Extensions to GROUP BY
MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause.
You can use this feature to get better performance by avoiding
unnecessary column sorting and grouping. However, this is useful
primarily when all values in each nonaggregated column not named in
the GROUP BY are the same for each group. The server is free to
choose any value from each group, so unless they are the same, the
values chosen are indeterminate.
In your case, you are gouping by U.USER_ID and selecting un-aggregated columns E.EMP_NAME,O.NAME

Related

inner join to get row with max column value

I have been trying to get the value of rows where the column value is max.
but it's somehow not working. please help out a bit.
Let me explain the problem
table 1 name = agency
columns agency_id, agency_name
table 2 name = client
columns client_name, total_bill, agency_id
what i want to get is the client name, agency name and total_bill of the row
for which total_bill value is maximum.
here's the query I was using
SELECT a.agency_name
FROM agency a
INNER JOIN (SELECT agency_id, client_name, MAX(total_bill) total_bill FROM client GROUP BY agency_id ) c
ON a.agency_id = c.agency_id;
could you tell me where I am going wrong with this?
I am getting this error -
Expression #2 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'agency-app.client.client_name' which is not
functionally dependent on columns in GROUP BY clause; this is incompatible
with sql_mode=only_full_group_by
do let me know how to fix this.
If you want the overall top customer, you can just join, order and limit:
select
a.agency_name,
c.client_name,
c.total_bill
from agencies a
inner join clients c on c.agency_id = a.agency_id
order by c.total_bill desc
limit 1
Try this query:
SELECT client.name, agency.name, client.total_bill
FROM agency, client
WHERE agency.agency_id=client.agency_id
AND client.total_bill=(SELECT MAX(total_bill) FROM client)

Very slow sql query for count

I need get report count for each user role, but my sql query very slow (40 sec on good server). My sql query:
SELECT `auth_assignment`.`item_name`, COUNT(*) as count
FROM `report`
LEFT JOIN `company` ON company.id = report.company_id
LEFT JOIN `auth_assignment`
ON auth_assignment.user_id = company.user_id
GROUP BY `auth_assignment`.`item_name`
ORDER BY `count`
auth_assignment.item_name is role type.
auth_assignment has ~23k rows.
company ~11k rows.
reports ~12k rows (one company can have many reports).
report.id and company.id, have binding
First, you are aggregating on a column from the third table in a left join. I'm guessing you don't want NULL for the value, so use inner join or change the order of the tables.
Table aliases make the query easier to write and to read:
SELECT aa.item_name, COUNT(*) as cnt
FROM report r JOIN
company c
ON c.id = r.company_id JOIN
auth_assignment aa
ON aa.user_id = c.user_id
GROUP BY aa.item_name
ORDER BY cnt;
Assuming the join's are correct for the tables, then you just want to be sure that you have indexes. These should go on the columns used for the joins: company(id, user_id), auth_assignment(user_id, item_name).

Filter query by ID

I'm trying to retrieve all the product information, filtering by product category id. The result should be hundreds of products but only returns 5 items. Whats wrong with my query?
SELECT product.id_product,
product.reference,
product.price,
product.active,
product.quantity,
product.id_category_default,
lang.name AS product_name,
lang.description,
lang.link_rewrite AS product_link_rewrite,
category.name AS category_name,
category.link_rewrite AS category_link_rewrite,
image.id_image,
product.id_manufacturer,
discount.reduction,
manufacturer.name AS manufacturer_name
FROM ps_product product
LEFT JOIN ps_specific_price discount ON discount.id_product=product.id_product
LEFT JOIN ps_product_lang lang ON lang.id_product=product.id_product
LEFT JOIN ps_category_lang category ON category.id_category=product.id_category_default
LEFT JOIN ps_image image ON image.id_product=product.id_product
LEFT JOIN ps_manufacturer manufacturer ON manufacturer.id_manufacturer=product.id_manufacturer
WHERE product.active=1
AND product.quantity>=1
AND product.id_category_default IN
(
4,5,6,65,66,90,91,53,54,48,49,50,55,62,67,68,71,19,82,88,89,87,22,24,26,74,
76,77,28,78,79,97,98,99,93,96,35,36,38,39,100
)
GROUP BY product.id_product ASC
Perhaps something as simple as:
GROUP BY product.id_product ASC
needs to be:
ORDER BY product.id_product ASC
mySQL extends the group by clause so that any columns not in the group by may get an indeterminate value.
If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. ... The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
Options:
change group by to order by
add all columns to the group by
don't use group by at all.

MySQL Two Table Query Count

I have two tables A & B.
Table A
GROUP # | GROUP NAME
1 group a
2 group b
3 group c
Table B will have a column with group # and then a bunch of other data.
I'm trying to figure out how I can create a query that will return the GROUP NAME from TABLE A and the number of rows associated with each group name from TABLE B.
Essentially I'm trying to get the following output:
GROUP NAME | COUNT
group a x
group b y
group c z
I've been trying variations of the following to no avail...
SELECT DISTINCT "GROUP NAME", COUNT(*) from A, B where A.GROUPNUM = B.GROUPNUM;
You will need to apply the aggregate COUNT() over the group GROUP NAME (using GROUP BY) to get the count you are looking for. DISTINCT doesn't come into play in this instance,
Note that a column name with spaces will need to be quoted using backticks, not single or double quotes. I'm also replacing your implicit join with an explicit INNER JOIN, which is the modern preferred syntax.
SELECT
`GROUP NAME`,
COUNT(B.GROUPNUM)
FROM
A
INNER JOIN B ON A.GROUPNUM = B.GROUPNUM
GROUP BY `GROUP NAME`
Here's a little demonstration: http://sqlfiddle.com/#!2/2123f/2
Try the below, note that you will want to use a left join (like below) if you also want to show group names on table a that have no rows on table b.
select a.group_name, count(b.groupnum)
from a
left join b
on a.groupnum = b.groupnum
group by a.group_name

MySQL left join counts

I have a left join to a table and want to count columns from it, after grouping by a column of the parent table:
SELECT * , COUNT(list.id) AS listcount, COUNT(uploads.id) AS uploadcount
FROM members
LEFT JOIN lists ON members.id= list.mid
LEFT JOIN uploads ON members.id= uploads.mid
GROUP BY members.id
Assume that a user can have either lists or uploads based on the type of user. Then is above query good enough? If not why?
Or do I have to use this query?
SELECT * , l.listcount, u.uploadcount
FROM members
LEFT JOIN (select count(lists.id) as listscount,mid from lists group by mid) as l
on l.mid = m.id
LEFT JOIN (select count(uploads.id) as uploadscount
,mid from uploads group by mid) as u on u.mid = m.id
GROUP BY members.id
Or correlated subqueries?
SELECT *,
(select count(lists.id) as listscount from lists as l where l.mid = m.id
group by mid) as listcount
(select count(uploads.id) from uploads as u where u.mid = m.id
group by mid) as uploadscount
FROM members
GROUP BY members.id
And which is best solution?
The alias m for members is missing in query 2 and 3. Otherwise they should give the same numbers.
Query 2 (fixed) will perform fastest.
Query 1 is different in that it will give a higher number for uploads, if there are cases of multiple lists per member. After joining to lists, there will be multiple rows for a member too, which will increase the count for uploads. So query 1 is probably wrong.
Also, NULL values are not counted. The manual informs:
COUNT(expr)
Returns a count of the number of non-NULL values of expr in the rows
retrieved by a SELECT statement. The result is a BIGINT value.