I have a MySQL table people like this:
id
person_id
meeting_time
1
21
123456
2
21
123457
3
21
123456
4
22
123470
5
21
0
6
21
123472
I need to get 1 row for each person_id, but only, if meeting_time is between 123451 and 123460. If it is not I don't need the row.
Also I don't need a lower id with higher meeting_time (like id 2) nor I need id 5. However currently I'm getting id 2, instead of id 3.
Here is my query:
SELECT MAX(`id`) AS `id`, `person_id`, `meeting_time`
FROM `people`
WHERE `meeting_time` > 123451 AND `meeting_time` < 123460
ORDER BY `id` DESC
Edit: The answer given by SelVazi works, so far, however: Since there is id 6 (I expanded the table with this entry), which has meeting_time greater than the max range I should not get any entries, but I'm getting id 3 (which was correct before I remembered I need that too).
Edit 2: MySQL server 5.5
You can use a correlated subquery. It assumes that id is unique:
select *
from t
where id = (
select max(id)
from t as x
where x.person_id = t.person_id
and meeting_time between 123451 and 123460
);
You can do it using inner join :
This is to look for the max id grouped by person_id then check if meeting_time is between 123451 and 123460
with cte as (
select p.*
from people p
inner join (
SELECT person_id, max(id) as id
FROM people
where meeting_time between 123451 and 123460
group by person_id
) as s on s.id = p.id
)
select c.*
from cte c
inner join (
SELECT person_id, MAX(meeting_time) as max_meeting_time
FROM people
group by person_id
) as s on s.person_id = c.person_id and s.max_meeting_time between 123451 and 123460
Demo here
This is a working query for mysql 5.5
select c.*
from (
select p.*
from people p
inner join (
SELECT person_id, max(id) as id
FROM people
where meeting_time between 123451 and 123460
group by person_id
) as s on s.id = p.id
) as c
inner join (
SELECT person_id, MAX(meeting_time) as max_meeting_time
FROM people
group by person_id
) as s on s.person_id = c.person_id and s.max_meeting_time between 123451 and 123460
Demo here
Related
I have a table with data similar to below
id UserId Category
1 5001 A
2 5001 B
3 5002 A
4 5003 B
5 5004 A
6 5001 A
1) How do we query table which can fetch me users who have registered only for A category. The user should not be registered for B or any other category.
For the data above, it should return me only
3 5002 A
2) How do we write a query which can fetch the users who have registered for both A and B category. Not alone A and Not alone B
For the above, it should return me only
userId - 5001
Can someone help on this ?
You can use the following solution, using IN:
SELECT DISTINCT UserID, Category
FROM table_name t
WHERE Category = 'A' AND UserID NOT IN (
SELECT UserID
FROM table_name
WHERE Category <> t.Category
);
Another solution using EXISTS:
SELECT DISTINCT UserID, Category
FROM table_name t
WHERE Category = 'A' AND NOT EXISTS (
SELECT 1
FROM table_name
WHERE UserID = t.UserID AND Category <> t.Category
);
To get the second result, you can use the following solution using a INNER JOIN:
SELECT DISTINCT t.UserId
FROM table_name t INNER JOIN (
SELECT UserId
FROM table_name
WHERE Category = 'B'
) b ON t.UserId = b.UserId
WHERE t.Category = 'A'
Another solution using EXISTS:
SELECT DISTINCT UserID
FROM table_name t
WHERE Category = 'A' AND EXISTS (
SELECT 1
FROM table_name
WHERE UserID = t.UserID AND Category = 'B'
);
demo on dbfiddle.uk
I have this query where i get all double entries with the same articleID and the categoryID = 2153
Now i want to delete this rows. But this seems not to work directly.
So i tried it with subquery, but when i use IN i would need a subquery which returns only the id. But that's also not possible.
How can i delete the rows from this query?
SELECT id, articleID, categoryID, count(*) AS count
FROM `s_articles_categories`
GROUP BY articleID
HAVING count(*) > 1 AND categoryID = 2153
Assuming that the id is the primary key for the table s_articles_categories You could use a join on the subselect result.
To delete all rows :
delete r.*
from s_articles_categories r
INNER JOIN (
SELECT id, articleID, categoryID, count(*) AS count FROM
`s_articles_categories` r
GROUP BY articleID
HAVING count(*) > 1 AND categoryID = 2153
) t on t.id = r.id
If you want to delete all duplicates but keep one of them in each group, then you can use the following query :
DELETE FROM `s_articles_categories` s
WHERE s.categoryID = 2153 AND EXISTS (
SELECT 1
FROM `s_articles_categories` s1
WHERE s1.articleID = s.articleID AND s1.categoryID = s.categoryID AND s1.id < s.id
)
I would recommend writing this as:
delete ac
from s_articles_categories ac join
(select articleId, categoryid, min(id) as min_id
from s_articles_categories
where categoryID = 2153
group by articleId, categoryid
) ac2
on ac2.articleId = ac.articleId and
ac2.categoryid = ac.categoryid and
ac.id > ac2.min_id
Trying to get this mysql query to work.
Explanation: There are two tables, one with all projects with org id columns, the second has all activities with column projectid that relates to the project table. I would like to count all activities within the activities table that has the userid and is active with 1.
But here comes the tricky part, I cannot get working. It does not collect the projects that are missing in activities table and present these with count 0. I would like to show all project that correspond with a unique projectid within bo
SELECT p1.`id` AS projectid ,count(a1.`id`) AS activitiescount ,a1.`userid` AS userid ,p1.`orgid` AS orgid
FROM `projects` AS p1
LEFT JOIN `activities` AS a1
ON p1.`id`=a1.`projectid`
WHERE p1.`orgid`=3
AND a1.`userid` = 26
AND a1.`active`=1
OR a1.`id` IS null
GROUP BY p1.`id`
ORDER BY p1.`name` DESC
Gives:
As you can see, the is not correct with 6 and 2 for example.
Please help. Thank you.
Untested:
Moved limits on Activities to the join.
Also the OR brought back more than you wanted, by moving the where clause around that problem should be resolved as well.
Standard Approach:
SELECT p1.`id` AS projectid
, count(a1.`id`) AS activitiescount
, a1.`userid` AS userid
, p1.`orgid` AS orgid
FROM `projects` AS p1
LEFT JOIN `activities` AS a1
ON p1.`id`=a1.`projectid`
AND a1.`userid` = 26
AND a1.`active`=1
WHERE p1.`orgid`=3
GROUP BY p1.`id`
ORDER BY p1.`name` DESC
your approach w/ ()'s correctly placed.
SELECT
p1.`id` AS projectid
,count(a1.`id`) AS activitiescount
,a1.`userid` AS userid
,p1.`orgid` AS orgid
FROM `projects` AS p1
LEFT JOIN `activities` AS a1 ON p1.`id`=a1.`projectid`
WHERE p1.`orgid`=3
AND ((a1.`userid` = 26 AND a1.`active`=1) OR a1.`id` IS null)
GROUP BY p1.`id`
ORDER BY p1.`name` DESC
----Update to simulate full outer join per comment.
SELECT *
FROM (
SELECT p1.`id` AS projectid
, count(a1.`id`) AS activitiescount
, a1.`userid` AS userid
, p1.`orgid` AS orgid
FROM `projects` AS p1
LEFT JOIN `activities` AS a1
ON p1.`id`=a1.`projectid`
AND a1.`userid` = 26
AND a1.`active`=1
WHERE p1.`orgid`=3
GROUP BY p1.`id`
UNION
SELECT p1.`id` AS projectid
, count(a1.`id`) AS activitiescount
, a1.`userid` AS userid
, p1.`orgid` AS orgid
FROM `projects` AS p1
RIGHT JOIN `activities` AS a1
ON p1.`id`=a1.`projectid`
AND p1.`orgid`=3
WHERE a1.`userid` = 26
AND a1.`active`=1
GROUP BY p1.`id`)
ORDER BY p1.`id`,A1.ID -- assumes A1.ID exists and you want to order in that fashion.
Good day everyone I would like a query that can give me both maximum and minimum sum values. Specifically i have the following tables:
PRODUCT
_____________________________
productID | categoryID| name|
__________|___________|_____|
1 1 "name1"
2 1 "name2"
3 1 "name3"
4 2 "name4"
5 2 "name5"
6 1 "name6"
7 2 "name7"
8 2 "name8"
AND:
PURCHASES
_____________________________
purchaseID | productID| quantity|
___________|___________|_________|
1 1 12
2 2 13
3 4 55
4 4 66
5 5 99
6 6 99
7 5 88
8 7 12
so basically i have to show the product that was bought the most and the product that was bought the least.. T have tried this:
SELECT pr.name, max(sum(p2.quantity))
FROM purchase as p2, product as pr
WHERE p2.IDproduct=pr.IDproduct
Group by p2.IDproduct desc
but I get Error Code 1111: Invalid use of group function.
For max Product
select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1
FOR COMBINE RESULT
(select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1)
UNION ALL
(select t1.name,min(t1.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t1
group by t1.name order by MaxProduct asc limit 1)
SQL FIDDLE
Hacky, but it works
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant DESC
LIMIT 1
)
UNION
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant ASC
LIMIT 1
)
SQLFiddle
As I received a Cannot perform an aggregate function on an expression containing an aggregate or a subquery as an error error.
For others encountering the problem of using the SUM function inside of a MAX function, but not having the same issue as OP, based on Luv's answer, I was able to convert the following Scalar-valued function:
SELECT #MinMaxValue = MAX(SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal))
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
to
SELECT #MinMaxValue = MAX(selectedsum.sumx)
FROM (
SELECT SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal) AS sumx
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
or if ArtikelM.Aantal could be zero
SELECT sumx =
CASE
WHEN SUM(ArtikelM.Aantal) > 0
THEN SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal)
ELSE MIN(Leverancier.FactPrijs)
END
FROM ArtikelM
INNER JOIN Leverancier
ON ArtikelM.LevId = Leverancier.LevId
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
I think this might help out others too
Select max(product_id), min(product_id)
from Purchases Where Product_id In
(select product_id, Sum(quantity) from Purchases Group by product_id)
I have social application let's say like twitter, where user can follow other users and can likes some comments.
What I need to fetch is followers of a user and ids of last 2 comments liked by each follower(if any), also the count of follower's followers, using MySQL.
Here are the tables
Table user_follower
User_id follower_id
1 2
2 3
1 5
1 6
1 7
Table user_likes
comment_id User_id date
41 2 some_date
42 2 some_date
41 5 some_date
42 5 some_date
43 5 some_date
43 2 some_date
43 6 some_date
how can we do this in a single mysql query?
so far i am able to get the followers and count of follower's follower and following both.
select uf.follower_id,
(select count(*) from user_followers uf1 where uf1.follower_id = uf.follower_id) as following_count,
(select count(*) from user_followers uf2 where uf2.user_id = uf.follower_id) as follower_count,
from user_followers uf
join users u on u.id = uf.follower_id
where uf.user_id = 1
what i want is now to get the 2 latest comment_ids for each follower, i.e. uf.follower_id here.
if not possible in the same query,
i am fine even with another query as will passing the follower_ids as in parameter, but it should give me 2 latest comment for each passed id..
I think this will work. I have not tested it so it may have some syntax errors. Given the level of nesting used in this query I suspect it will perform badly with a very large dataset.
SELECT follower_id, num_followers, GROUP_CONCAT(comment_id)
FROM (
SELECT t.*,
#r := IF(#g = t.follower_id, #r+1, 1) RowNum,
#g := t.follower_id
FROM (select #g:=null) AS initvars
INNER JOIN (
SELECT followers.*, ul.comment_id
FROM (
SELECT
uf1.user_id,
uf1.follower_id,
COUNT(uf2.follower_id) AS num_followers
FROM user_follower uf1
LEFT JOIN user_follower uf2
ON uf1.follower_id = uf2.user_id
WHERE uf1.user_id = 1
GROUP BY uf1.user_id, uf1.follower_id
) AS followers
LEFT JOIN user_likes ul
ON followers.follower_id = ul.user_id
ORDER BY followers.follower_id ASC, comment_id DESC
) AS t
) AS final
WHERE RowNum < 3
GROUP BY follower_id, num_followers;
UPDATE Here is the other query using the inequality join -
SELECT tmp.follower_id, COUNT(uf2.follower_id) AS num_followers, tmp.comments
FROM (
SELECT follower_id, GROUP_CONCAT(comment_id ORDER BY comment_id DESC) AS comments
FROM (
SELECT uf.follower_id, ul1.*
FROM user_follower uf
LEFT JOIN user_likes ul1
ON uf.follower_id = ul1.user_id
LEFT JOIN user_likes ul2
ON uf.follower_id = ul2.user_id
AND ul1.comment_id < ul2.comment_id
WHERE uf.user_id = 1
GROUP BY ul1.user_id, ul1.comment_id
HAVING COUNT(ul2.comment_id) < 2
) AS tmp
GROUP BY tmp.follower_id
) AS tmp
LEFT JOIN user_follower uf2
ON tmp.follower_id = uf2.user_id
GROUP BY tmp.follower_id