MySQL: Sorting results before group by statement - mysql

Basically, I have a coppermine gallery and I want to show the last 4 updated albums on the homepage. Here's the query that I've got so far. It basically gets the latest pictures. The subquery works fine on it's own but when it comes time to grouping them to get each album on its own, it doesn't seem to be getting the most recent one from the list.
SELECT *
FROM (
SELECT c.cid, c.name AS catname, a.aid, a.title AS albumtitle, a.category, p.aid AS albumid,p.filepath,p.filename,p.ctime AS creationtime,p.title AS pictitle,p.approved
FROM cpg145_pictures AS p LEFT JOIN `cpg145_albums` AS a ON p.aid = a.aid LEFT JOIN `cpg145_categories` AS c ON a.category = c.cid
WHERE p.approved='YES' AND a.category IN (47,48)
ORDER BY p.ctime DESC) AS T
GROUP BY albumid
ORDER BY creationtime DESC
LIMIT 4

I figured out the answer. Apparently, in MariaDB you have to give the subquery a limit for it to be sorted correctly. So:
SELECT *
FROM (
SELECT c.cid, c.name AS catname, a.aid, a.title AS albumtitle, a.category, p.aid AS albumid,p.filepath,p.filename,p.ctime AS creationtime,p.title AS pictitle,p.approved
FROM cpg145_pictures AS p LEFT JOIN `cpg145_albums` AS a ON p.aid = a.aid LEFT JOIN `cpg145_categories` AS c ON a.category = c.cid
WHERE p.approved='YES' AND a.category IN (47,48)
ORDER BY p.ctime DESC
LIMIT 200) AS T
GROUP BY albumid
ORDER BY creationtime DESC
LIMIT 4

Related

mySQL: Issue with Left Join

I have the following query:
SELECT c.`entity_id`,c. p.`name` as parent_id, c.`name`
FROM category c
LEFT JOIN category p WHERE c.`parent_id = p.id
WHERE c.is_active = 1
ORDER BY c.parent_id ASC, c.position ASC;
But I get an error on the first WHERE clause, can anyone spot the error here? Thanks
You have added where clause twice. Try as below :
SELECT c.`entity_id`,c. p.`name` as parent_id, c.`name`
FROM category c
LEFT JOIN category p on c.`parent_id = p.id
Where c.is_active = 1
ORDER BY c.parent_id ASC, c.position ASC;

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

HQL/SQL select top 10 records based on count

I have 2 tables:
CATEGORY (id)
POSTING (id, categoryId)
I am trying to write an HQL or SQL query to find top 10 Categories which have the most number of Postings.
Help is appreciated.
SQL query:
SELECT c.Id, sub.POSTINGCOUNT
FROM CATEGORY c where c.Id IN
(
SELECT TOP 10 p.categoryId
FROM POSTING p
GROUP BY p.categoryId
order by count(1) desc
)
HQL:
Session.CreateQuery("select c.Id
FROM CATEGORY c where c.Id IN
(
SELECT p.categoryId
FROM POSTING p
GROUP BY p.categoryId
order by count(1) desc
)").SetMaxResults(10).List();
http://sqlinthewild.co.za/index.php/2010/01/12/in-vs-inner-join/
In SQL you can do this:
SELECT c.Id, sub.POSTINGCOUNT
FROM CATEGORY c
INNER JOIN
(
SELECT p.categoryId, COUNT(id) AS 'POSTINGCOUNT'
FROM POSTING p
GROUP BY p.categoryId
) sub ON c.Id = sub.categoryId
ORDER BY POSTINGCOUNT DESC
LIMIT 10
SQL can be like :
SELECT c.* from CATEGORY c, (SELECT count(id) as postings_count,categoryId
FROM POSTING
GROUP BY categoryId ORDER BY postings_count
LIMIT 10) d where c.id=d.categoryId
This output can be mapped to the Category entity.
I know that is an old question, but i reached a satisfatory answer.
JPQL:
//the join clause is necessary, because you cannot use p.category in group by clause directly
#NamedQuery(name="Category.topN",
query="select c, count(p.id) as uses
from Posting p
join p.category c
group by c order by uses desc ")
Java:
List<Object[]> list = getEntityManager().createNamedQuery("Category.topN", Object[].class)
.setMaxResults(10)
.getResultList();
//here we must made a conversion, because the JPA cannot order using a non select field (used stream API, but you can do it in old way)
List<Category> cats = list.stream().map(oa -> (Category) oa[0]).collect(Collectors.toList());

Mysql Join issue and i want this result

I have two tables 1 and 2 or i need this result (see my image 1) using Join in mysql also see my Query for verification
SELECT c.`id`,
c.`name`,
COUNT(*) AS `totalcount`
FROM categories c INNER JOIN subcategories sc
ON c.`id` = sc.`cat_id`
GROUP BY c.`id`
ORDER BY c.added_date DESC
I want this result
Table 1
Table 2
Help are definitely appreciated
USE LEFT JOIN instead of INNER JOIN
try this:
SELECT a.`id`, a.`name`, count(b.`cat_id`) as totalCount
FROM categories a LEFT JOIN subcategories b
on a.id = b.cat_ID
GROUP BY a.`id`
ORDER BY a.added_date desc
Use LEFT JOIN instead of INNER JOIN -
SELECT c.`id`, c.`name`,
COUNT(sc.cat_id) AS `totalcount`
FROM categories c LEFT JOIN
subcategories sc
ON c.`id` = sc.`cat_id`
GROUP BY c.`id`
ORDER BY c.added_date DESC;
A demo is here.