error in sql when using group by - mysql

I have this query to group together article authors on my site, along with how many articles they've done recently and their most recent posted date.
The problem is this error:
#1055 - Expression #4 of SELECT list is not in GROUP BY clause and
contains nonaggregated column 'goltest.a.author_id' which is not
functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
SELECT
COUNT(DISTINCT a.article_id) AS `counter`,
u.username,
u.user_id,
(
SELECT
`date`
FROM
`articles`
WHERE
`author_id` = a.`author_id`
ORDER BY
`article_id`
DESC
LIMIT 1
) AS `last_date`
FROM
`articles` a
LEFT JOIN
`users` u
ON
u.user_id = a.author_id
LEFT JOIN
`article_category_reference` c
ON
a.`article_id` = c.`article_id`
WHERE
a.`date` >= 1491004800 AND a.`date` <= 1495018102 AND a.`active` = 1 AND c.`category_id` NOT IN(63) AND a.author_id != 1844
GROUP BY
u.`username`,
u.`user_id`
ORDER BY
`counter`
DESC
,
a.date
DESC
Don't really understand why it wants "author_id" in the group by list, since I'm not selecting it?

For those interested I fixed it with this, replacing the subquery with MAX() value for the date:
SELECT
COUNT(DISTINCT a.article_id) AS `counter`,
u.username,
u.user_id,
MAX(a.date) AS `last_date`
FROM
`articles` a
LEFT JOIN
`users` u
ON
u.user_id = a.author_id
LEFT JOIN
`article_category_reference` c
ON
a.`article_id` = c.`article_id`
WHERE
a.`date` >= 1491004800 AND a.`date` <= 1495018102 AND a.`active` = 1 AND c.`category_id` NOT IN(63) AND a.author_id != 1844
GROUP BY
u.`username`,
u.`user_id`
ORDER BY
`counter`
DESC
,
last_date
DESC
With thanks to Shadow for pointing out "max" :)

Related

how to sort and group by by it's count

I have the following:
SELECT DISTINCT s.username, COUNT( v.id ) AS cnt
FROM `instagram_item_viewer` v
INNER JOIN `instagram_shop_picture` p ON v.item_id = p.id
INNER JOIN `instagram_shop` s ON p.shop_id = s.id
AND s.expirydate IS NULL
AND s.isLocked =0
AND v.created >= '2014-08-01'
GROUP BY (
s.id
)
ORDER BY cnt DESC
Basically I have an instagram_item_viewer with the following structure:
id viewer_id item_id created
It tracks when a user has viewed an item and what time. So basically I wanted to find shops that has the most items viewed. I tried the query above and it executed fine, however it doesn't seem to give the appropriate data, it should have more count than what it is. What am I doing wrong?
First, with a group by statement, you don't need the DISTINCT clause. The grouping takes care of making your records distinct.
You may want to reconsider the order of your tables. Since you are interested in the shops, start there.
Select s.username, count(v.id)
From instagram_shop s
INNER JOIN instagram_shop_picture p ON p.shop_id = s.shop_id
INNER JOIN instagram_item_viewer v ON v.item_id = p.id
AND v.created >= '2014-08-01'
WHERE s.expirydate IS NULL
AND s.isLocked = 0
GROUP BY s.username
Give thata shot.
As mentioned by #Lennart, if you have a sample data it would be helpful. Because otherwise there will be assumptions.
Try run this to debug (this is not the answer yet)
SELECT s.username, p.id, COUNT( v.id ) AS cnt
FROM `instagram_item_viewer` v
INNER JOIN `instagram_shop_picture` p ON v.item_id = p.id
INNER JOIN `instagram_shop` s ON p.shop_id = s.id
AND s.expirydate IS NULL
AND s.isLocked =0
AND v.created >= '2014-08-01'
GROUP BY (
s.username, p.id
)
ORDER BY cnt DESC
The problem here is the store and item viewer is too far apart (i.e. bridged via shop_picture). Thus shop_picture needs to be in the SELECT statement.
Your original query only gets the first shop_picture count for that store that is why it is less than expected
Ultimately if you still want to achieve your goal, you can expand my SQL above to
SELECT x.username, SUM(x.cnt) -- or COUNT(x.cnt) depending on what you want
FROM
(
SELECT s.username, p.id, COUNT( v.id ) AS cnt
FROM `instagram_item_viewer` v
INNER JOIN `instagram_shop_picture` p ON v.item_id = p.id
INNER JOIN `instagram_shop` s ON p.shop_id = s.id
AND s.expirydate IS NULL
AND s.isLocked =0
AND v.created >= '2014-08-01'
GROUP BY (
s.username, p.id
)
ORDER BY cnt DESC
) x
GROUP BY x.username

City_id in the where clause is ambiguous

I have wrote the query , but it is showing city id in the where clause is ambigious
SELECT
`a`.`name`,
`a`.`company`,
`a`.`city`,
`a`.`country`,
`a`.`phone`,
`a`.`type_of_enquiry`,
`b`.`enquiry_id`,
`a`.`hearaboutus`,
`a`.`email`,
`a`.`comments`,
`a`.`address`,
`c`.`id`,
`c`.`city_id`
FROM (`sobha_enquiry` a)
LEFT JOIN `sobha_enquiryzone` b
ON `b`.`enquiry_id` = `a`.`id`
LEFT JOIN `sobha_admin` c
ON `c`.`city_id` = `b`.`city_id`
WHERE `city_id` = '2'
GROUP BY `a`.`id`
ORDER BY `id` desc, `a`.`id` DESC
Pls help me !!!!!!!!!!
SELECT
`a`.`name`,
`a`.`company`,
`a`.`city`,
`a`.`country`,
`a`.`phone`,
`a`.`type_of_enquiry`,
`b`.`enquiry_id`,
`a`.`hearaboutus`,
`a`.`email`,
`a`.`comments`,
`a`.`address`,
`c`.`id`,
`c`.`city_id`
FROM (`sobha_enquiry` a)
LEFT JOIN `sobha_enquiryzone` b
ON `b`.`enquiry_id` = `a`.`id`
LEFT JOIN `sobha_admin` c
ON `c`.`city_id` = `b`.`city_id`
WHERE `a`.`city_id` = '2'
GROUP BY `a`.`id`
ORDER BY `c`.`id` desc, `a`.`id` DESC
In you where clause you should provide either b or c because are using aliases and the columns city_id exists in both table which is confusing mysql
the problem lies in the WHERE clause, you need to specify what table will be search for city_id sice both of them contains the same column name. It could be either from sobha_enquiryzone or from sobha_admin.
SELECT a.NAME,
a.company,
a.city,
a.country,
a.phone,
a.type_of_enquiry,
b.enquiry_id,
a.hearaboutus,
a.email,
a.comments,
a.address,
c.id,
c.city_id
FROM sobha_enquiry a
LEFT JOIN sobha_enquiryzone b
ON b.enquiry_id = a.id
LEFT JOIN sobha_admin c
ON c.city_id = b.city_id
WHERE b.city_id = '2' -- or c.city_id = '2' (both will yield the same result)
GROUP BY a.id
ORDER BY id DESC, a.id DESC

Selecting from a Select statement: Every derived table must have its own alias

I need to retrieve the last 3 rows but in an ASC order, so here's the final query:
SELECT c.comment_id,c.comment_message,c.comment_date,u.user_id,u.first_name,u.last_name,p.profile_picture_path
FROM
(SELECT c.comment_id,c.comment_message,c.comment_date,u.user_id,u.first_name,u.last_name,p.profile_picture_path
FROM posts_comments c,users u,users_profile_pictures p
WHERE c.user_id = u.user_id AND u.user_id = p.user_id AND c.post_id = '82'
ORDER BY c.comment_date DESC
LIMIT 3)
ORDER BY c.comment_date ASC
I know there's something wrong here, I'm receiving this error: Every derived table must have its own alias. How do I select columns from a Select statement when they are pointed out by their appropriate tables? Means, how do I select c.comment_id?
SELECT comment_id,
comment_message,
comment_date,
user_id,
first_name,
last_name,
profile_picture_path
FROM (
SELECT c.comment_id,
c.comment_message,
c.comment_date,
u.user_id,
u.first_name,
u.last_name,
p.profile_picture_path
FROM posts_comments c,
users u,
users_profile_pictures p
WHERE c.user_id = u.user_id
AND u.user_id = p.user_id
AND c.post_id = '82'
ORDER BY c.comment_date DESC
LIMIT 3
) subA -- <<== put alias here
-- the purpose of the alias is to supply an identification
-- for the subquery
ORDER BY comment_date ASC
SELECT x.comment_id
, x.comment_message
, x.comment_date
, x.user_id
, x.first_name
, x.last_name
, x.profile_picture_path
FROM
( SELECT c.comment_id
, c.comment_message
, c.comment_date
, u.user_id
, u.first_name
, u.last_name
, p.profile_picture_path
FROM posts_comments c
JOIN users u
ON u.user_id = c.user_id
JOIN users_profile_pictures p
ON p.user_id = u.user_id
WHERE c.post_id = 82
ORDER
BY c.comment_date DESC
LIMIT 3
) x
ORDER
BY x.comment_date ASC;

MySQL random join

Here is my MySQL database:
And my query to get all subcategories:
SELECT `a`.`id`, `a`.`name`, `a`.`url_segment`, `a`.`categories_id`, `b`.`image` AS supplements_image
FROM (`subcategories` AS a)
LEFT JOIN `supplements` AS b ON `b`.`subcategories_id` = `a`.`id`
LEFT JOIN `reviews` AS c ON `c`.`supplements_id` = `b`.`id`
GROUP BY `a`.`id`
ORDER BY `a`.`categories_id` ASC, COUNT(c.id) DESC, `b`.`image` ASC
The problem is with the subcategory image, that should be the image of a random product inside that subcategory, but I'm always getting the image of the first product. Any idea how I can do this?
SELECT `a`.`id`, `a`.`name`, `a`.`url_segment`, `a`.`categories_id`,
(SELECT `image`
FROM `supplements`
WHERE `subcategories_id` = `a`.`id`
ORDER BY RAND() LIMIT 1
) AS supplements_image
FROM (`subcategories` AS a)
LEFT JOIN `reviews` AS c ON `c`.`supplements_id` = `a`.`id`
GROUP BY `a`.`id`
ORDER BY `a`.`categories_id` ASC, COUNT(c.id) DESC
Edited unspecified alias b and now works great: See fiddle!

SQL - Should I use a join?

I have the following sample query (MySQL):
SELECT * FROM `action`
WHERE `customer_id` IN
(SELECT `id` FROM `customer` WHERE `status`=1)
ORDER BY
action.date ASC
LIMIT 0, 10
I need to be able to ORDER BY the customer.status field. Do I accomplish this with a join?
status is a field on the customer table.
Edited Query:
SELECT * FROM `action`
ORDER BY
action.date ASC
LIMIT 0, 10
IMPORTANT!
I am parsing the return data via PHP. After running the revised query:
SELECT * FROM `action` a INNER JOIN `customer` c ON a.customer_id = c.id ORDER BY a.form_id ASC LIMIT 0, 10
My PHP code breaks...
This post helped me out.
My revised query looks like this:
SELECT
*, a.id AS lead_id, c.id AS customer_id
FROM
`action` a
INNER JOIN
`customer` c ON a.customer_id = c.id
ORDER BY c.status DESC
Thanks everyone!
UPDATE
Because I have some customer records without an action record, an INNER JOIN was not returning all relevant records. I use a JOIN now, and all results come back as expected.
SELECT *
FROM `action` a
INNER JOIN `customer` c on a.`customer_id` = c.`id`
WHERE c.`status` in (1, 4, 7, 8)
ORDER BY a.date, c.status
LIMIT 0, 10
You can do either:
SELECT * FROM `action` a
INNER JOIN `customer` c on c.id = a.customer_id
WHERE c.status = 1
ORDER BY a.date ASC, c.status
LIMIT 0, 10
Or:
SELECT * FROM `action` a
INNER JOIN `customer` c on (c.id = a.customer_id and c.status = 1)
ORDER BY a.date ASC, c.status
LIMIT 0, 10
EDIT:
It's probably worth pointing out there's no sense in ordering by c.status, as it will always be 1. However, I put that in there since it was brought up by others as well as mentioned in the OP. I would think it could be removed from both queries.
Yes, you may accomplish it with a join and may be faster:
SELECT * FROM `action` a join customer c on c.id=a.customer_id
where c.status=1
ORDER BY
a.date ASC
LIMIT 0, 10
Also, consider not using * and instead list the columns that you need. It will improve performance in case you need to select less than all columns and you won't get surprises in the future if the table changes.
SELECT * FROM `action` a
JOIN `customer` c on a.customer_id=c.id
WHERE c.status=1 order by a.date, c.status ASC
LIMIT 0, 10