sql select the product with most users - mysql

users:
uid int(11) - userid(primary key, auto_increment)
name varchar(255)
pass varchar(64)
created int(11)
projects:
pid int(11) .....
name varchar(150)
description varchar(255)
created int(11)
users_projects:
uid int(11) - user id
pid int(11) - product id
How can i select the project with the most ussers assigned to it?
sql query.

You could use something like this:
select p.pid,
p.name,
up.TotalUsers
from projects p
inner join
(
select pid, count(uid) TotalUsers
from users_projects
group by pid
) up
on p.pid = up.pid
order by TotalUsers Desc
-- limit 1
See SQL Fiddle with Demo
This will return the list of all projects and a count of the Total Users per project. If you want to return the project will the most users, then you will include the limit 1 that is commented out.
If you have more than one project that has the same number of users, then you would want to use something similar to this:
select p.pid,
p.name,
up.TotalUsers
from projects p
inner join
(
select pid, count(uid) TotalUsers
from users_projects
group by pid
) up
on p.pid = up.pid
where totalusers = (select count(*) Total
from users_projects
group by pid
order by total desc
limit 1)
See SQL Fiddle with Demo
Thanks #JW for the Fiddle

The following query will include multiple projects having the same number of users and happens to be the most number of users.
SELECT a.name userName, c.name ProjectName
FROM users a
INNER JOIN users_projects b
ON a.uid = b.uid
INNER JOIN projects c
ON b.pid = c.pid
INNER JOIN
(
SELECT pid, COUNT(*) totalCount
FROM users_projects
GROUP BY pid
HAVING COUNT(*) = (SELECT COUNT(*) x
FROM users_projects
GROUP BY pid
ORDER BY x DESC
LIMIT 1)
) d ON b.pid = d.pid
ORDER BY a.Name ASC
SQLFiddle Demo (with duplicate project)
SQLFiddle Demo

If you are looking for only one project, the following is the fastest way:
select project_id, count(*) as NumUsers
from user_projects
group by project_id
order by count(*) desc
limit 1
(I am assuming that "product" = "project").

Related

SQL count and sum some row

I am getting a calculation error in my code
SELECT dep_id,
dept_info.name AS dept_name,
count(dep_id) AS totalInovators,
count(user_id) AS totalIdea,
sum(POINT) AS totalpoint
FROM user_info
JOIN dept_info ON user_info.dep_id =dept_info.id
JOIN user_idea ON user_info.id=user_idea.user_id
GROUP BY dep_id
ORDER BY dep_id DESC
My output result:
Expected result:
With my table user_info :
My user_idea :
My dept_info :
Below the query that solve your problem:
select
user_info.dep_id,
dept_info.name,
count(*) as totalInovators,
sum(ideas_count) as totalIdea,
sum(point) as totalpoint
from
-- first we aggregate table user_idea
(select user_id, count(*) ideas_count from user_idea group by user_id) ideas
-- and after join rest of required tables
join user_info on ideas.user_id = user_info.id
join dept_info on dept_info.id = user_info.dep_id
group by user_info.dep_id, dept_info.name;
Working code here: SQLize.online
I suspect that you are joining along different dimensions. If so, a quick-and-easy solution uses count(distinct):
select d.id, d.name as dept_name, count(distinct u.id) as totalInovators,
count(*) as totalIdea, sum(i.point) as totalpoint
from user_info u join
dept_info d
on u.dep_id = d.id join
user_idea i
on u.id = i.user_id
group by d.id
order by d.id desc

How to run where exists with distinct faster

I have a query with WHERE EXISTS and DISTINCT. I just want to find distinct emails with same order_id
How can I make this faster
select DISTINCT(user_email)
from (
SELECT *
FROM orders mto
WHERE EXISTS
(
SELECT 1
FROM orders mti
WHERE mti.order_id = mto.order_id
LIMIT 1, 1
)
) as z
INNER JOIN marketplaces as u ON z.ump_id = u.id
You are doing excess/needless work - the EXISTS will always return TRUE in your situation.
If you want a list of all (unique) emails which have at least 1 order, then
SELECT
user_email
FROM
marketplaces
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id IS NOT NULL
GROUP BY user_email
If you want to get a list with all (unique) emails for a given order ID, then
SELECT
user_email
FROM
orders
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id = 17
GROUP BY user_email

MYSQL 1 to N JOIN

I have the following tables:
tasks ( id int PRIMARY KEY auto_increment,
description text,
created datetime,
modified datetime);
commentaries( id int PRIMARY KEY auto_increment,
task_id int,
user_id int,
description text,
created datetime );
users ( id int PRIMARY KEY auto_increment,
name varchar(300),
created datetime );
It's One-To-Many relationship (1-N).
I'm building an inbox, to list the last N tasks, and to show the last inserted commentary for each task?
EDIT1:
The query:
SELECT T.id, T.description, C.description, T.created
FROM tasks T LEFT JOIN commentaries C ON T.id = C.task_id AND C.id IN (
SELECT max(C.id) FROM tasks Task
LEFT JOIN commentaries C ON C.task_id = Task.id
WHERE Task.id in (select id from tasks WHERE user_id = 1 )
GROUP BY Task.id)
ORDER BY T.id DESC
LIMIT 10;
EDIT2
SQL Fiddle Link: http://sqlfiddle.com/#!2/1555c7/1
You can get the time of the last inserted commentary by using:
select task_id, max(created) as maxc
from commentaries
group by task_id;
You can get the last inserted commentary by using this in a join:
select t.*, c.*
from tasks t join
commentaries c
on c.task_id = t.id join
(select task_id, max(created) as maxc
from commentaries
group by task_id
) cmax
on cmax.task_id = c.task_id and cmax.maxc = c.created;
SELECT T.*, C.*
FROM tasks T
JOIN Commentaries C
ON T.id = C. task_id
GROUP BY T.id
ORDER BY C.task_id ASC
LIMIT 1
select * from task,com where task.id=com.task_id order by com.da desc limit 1;

MySQL: SELECT if non of group by members is equal to x

I have troubles getting proper data.
I have table structure like:
id INT(11) AI
order_id INT(11)
status varchar(45)
This table log status changes for orders.
So order_id's will have few statuses.
Now I need to select rows and group them by order_id, where order never had status (not even one status with given order_id) != 'example'
We don't show orders, where one of members had status = example
Sample data
1 12 ready
1 12 example
2 13 ready
2 13 sent
So I don't want order 12 to show at all, because one of it members have "example" status
I've tried grouping results, but it's not enough.
you can do it by simple join query :
select a.order_id
from ordrstatus as a left outer join (select orderid , count(*) as status from orderstatus where status = 'example' group by orderid) as b on a.orderid = b.orderid
where b.status = 0 or b.status is NUll
Join query always run faster then IN query . by using Join in query it will run only one time .
You can try like this...it will return all order id which never had status -example
Select
Order_id,
from TableName A where Not Exists(
Select id from TableName B where
status='example' and
a.Order_id=b.Order_id
)
group by Order_id
Not quite sure if you want the records for order which have had a status of example, or ones which have never had a status of example
To get a list of orders (with the status grouped up) which have had a status of example:-
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a
INNER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b
ON a.order_id = b.order_id
GROUP BY order_id
To get those which have NEVER had a status of exmaple
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a
LEFT OUTER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b
ON a.order_id = b.order_id
WHERE b.order_id IS NULL
GROUP BY order_id
EDIT
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a -- Statuses
LEFT OUTER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b -- Get any order id which has had a status of example (as a LEFT JOIN)
ON a.order_id = b.order_id
INNER JOIN
(
SELECT order_id, MAX(id) AS Latestid
FROM SomeTable
GROUP BY order_id
) c -- Get the latest status for each order (ie, max id)
ON a.order_id = c.order_id
LEFT OUTER JOIN
(
SELECT order_id, id
FROM SomeTable
WHERE status = 'example2'
) d -- Get the id of the order status of example2
ON a.order_id = d.order_id AND c.Latestid = d.id -- join on the same order id and that the record id matches the latest record id
WHERE b.order_id IS NULL -- reject those where a match was found on example for any status
AND d.order_id IS NULL -- reject those where a match was found on example2 for the latest status
GROUP BY order_id
try this
SELECT Order_ID FROM tbl_Orders
WHERE Status NOT IN ('example')
GROUP BY Order_ID
SELECT DISTINCT x.order_id
FROM order_status x
LEFT
JOIN order_status y
ON y.order_id = x.order_id
AND y.status = 'example'
WHERE y.id IS NULL;

How to fetch all rows with left join getting the latest row in second table

I am trying to follow the instructions in this answer how to get the latest row in the joined table.
I have two tables.
Projects : id, title
Status : project_id, status_id, created(DATETIME)
When I know the project ID (example = 2) I have the correct query to select the latest status update.
SELECT projects. * , project_state_project_map.status_id AS status,
project_state_project_map.created AS status_created
FROM projects
LEFT JOIN (
SELECT *
FROM project_state_project_map
WHERE project_id = 2
ORDER BY created DESC
LIMIT 1
)
project_state_project_map ON project_state_project_map.project_id = projects.id
WHERE projects.id = 2
LIMIT 1
However, I cannot figure out how to select all projects with their current status. What do I have to change to the sql to get all projects with their latest states.
I would suggest altering your query to use an aggregate function to get the latest date with status:
SELECT p. *,
pm1.status_id AS status,
pm1.created AS status_created
FROM projects p
LEFT JOIN project_state_project_map pm1
ON pm1.project_id = p.id
INNER JOIN
(
SELECT max(created) MaxDate, project_id
FROM project_state_project_map
WHERE project_id = 2
GROUP BY project_id
) pm2
ON pm1.project_id = pm2.project_id
AND pm1.created = pm2.MaxDate
WHERE p.id = 2
This gets the max(created) date for each project, then this result is used to return the status with that date.
This could also be written as:
SELECT p. *,
pm.status_id AS status,
pm.created AS status_created
FROM projects p
LEFT JOIN
(
SELECT pm1.project_id,
pm1.status_id,
pm1.created
FROM project_state_project_map pm1
INNER JOIN
(
SELECT max(created) MaxDate, project_id
FROM project_state_project_map
WHERE project_id = 2
GROUP BY project_id
) pm2
ON pm1.project_id = pm2.project_id
AND pm1.created = pm2.MaxDate
) pm
ON pm.project_id = p.id
WHERE p.id = 2;