+----+----------+-------------+-----------+---------------------+---------+---------------------------+
| id | action | object_type | object_id | created_at | user_id | object_title |
+----+----------+-------------+-----------+---------------------+---------+---------------------------+
| 1 | shared | 0 | 1 | 2016-04-22 06:13:16 | 1 | 5 highest buildings |
| 2 | liked | 0 | 1 | 2016-04-22 06:15:02 | 1 | 5 highest buildings |
| 3 | liked | 0 | 1 | 2016-05-21 19:02:18 | 2 | 5 highest buildings |
| 4 | liked | 1 | 3 | 2016-05-21 19:02:21 | 3 | 5 largest bridges |
+----+----------+-------------+-----------+---------------------+---------+---------------------------+
I'm trying to build some thing similar to Facebook's news feed. I mean when multiple users in my friend list like same post, we will show only single result in th news feed saying that friend1, friend2, frnd3, etc., like this xyz post.
From this table I would like to group by on these three columns (action, object_type, object_id) and a list of users for this object.
SELECT *
FROM mytable
GROUP BY action, object_type, object_id
But this gave me some weird results, and I was expecting a list of users. I' really don't have any clue how to do that in this query.
Any help or lead will be appreciated.
Try this query
SELECT action, object_title,count(user_id) as user_count, group_concat(user_id) as user_ids
FROM mytable GROUP BY action, object_type, object_id;
Related
I've been trying to get this going for hours and haven't figured this out yet.
Say I've got 2 tables - master and details.
master/detail has the following data
master table
+------+-------+
| id | name |
+------+-------+
| 1 | jeff |
| 2 | simon |
| 3 | andy |
| 4 | jerry |
+------+-------+
details table
+----+-----------+---------+
| id | master_id | tag |
+----+-----------+---------+
| 1 | 1 | WINDOWS |
| 2 | 1 | MAC |
| 3 | 2 | MAC |
| 4 | 3 | WINDOWS |
| 5 | 3 | MAC |
| 6 | 3 | LINUX |
| 7 | 4 | MAC |
+----+-----------+---------+
how do I select the master records which has both tags 'WINDOWS', 'MAC'.
So it should only return master_id 1 and 3 which is jeff and andy only.
If I do a
select distinct(master_id) from details where tag in ('WINDOWS', 'MAC')
it gives me all of them.
Sorry for the newbie question but if anyone can help, it'll be much appreciated.
You need simple GROUP BY with HAVING clause :
select master_id
from details
where tag in ('WINDOWS', 'MAC')
group by master_id
having count(*) = 2;
If details table has duplicate tags for master_id then you need count(distinct tag).
YOu could use a join with count having 2 value only for tag
select distinct master_id
from detail
inner join (
select master_id from detail
group by master_id
having count(distinct tag) = 2
) t on t.master_id = detail.master_id and detail.tag in ('WINDOWS', 'MAC')
I have a table in which I link items to types where each type can have multiple categories. For each combination of type and category, only one item should be linked. However, through some past error of mine, some duplicates have slipped through. I am now trying to write a query that will give me the duplicates but I am not doing a great job or I wouldn't be posting here obviously.
SELECT
item_id,
type_id,
category
FROM itemTypes
WHERE category = 'cat1'
GROUP BY type_id
HAVING COUNT(*) >= 2;
This is what I tried. It does work and gives me the type_ids that are linked to different items. But each type_id should be linked to only one item. This list doesn't show me the items that are linked. And that is just the thing I would like to know.
Can someone help me out?
Update
Below is a data sample. As you can see type_id 5 and 6 are linked multiple times. What I would like to get as a result is only these records.
| id | item_id | type_id | cat |
+-------+-----------+-----------+-----------+
| 1 | 100 | 5 | cat1 |
| 2 | 110 | 5 | cat1 |
| 3 | 115 | 6 | cat1 |
| 4 | 120 | 7 | cat1 |
| 5 | 125 | 5 | cat1 |
| 6 | 130 | 6 | cat1 |
| 7 | 135 | 4 | cat1 |
| 8 | 140 | 8 | cat1 |
You need to join your itemTypes table to the query you currently have, rephrased as a subquery:
SELECT t1.*
FROM itemTypes t1
INNER JOIN
(
SELECT item_id
FROM itemTypes
WHERE category = 'cat1'
GROUP BY item_id
HAVING COUNT(*) > 1
) t2
ON t1.item_id = t2.item_id;
The logical problem with your current query is that it can only find item_id values which meet your criteria, but not the other column values.
I have an event table
+----------+------------+
| event_id | event_name |
+----------+------------+
| 1 | event1 |
| 2 | event2 |
| 3 | event3 |
| 4 | event4 |
+----------+------------+
And an event_performer table
+--------------------+----------+--------------+
| event_performer_id | event_id | performer_id |
+--------------------+----------+--------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 3 |
| 6 | 3 | 4 |
| 7 | 4 | 3 |
| 8 | 4 | 4 |
+--------------------+----------+--------------+
I want to get all the events with performer ids 1 and 2, so I run the following query:
select event.* from event
join event_performer
on event.event_id = event_performer.event_id
and performer_id in (1,2)
order by event_name
When I do that, I obviously get duplicate events (two for event_id 1 and two for event_id 2). What's the most efficient way in MySQL remove the duplicates so that I get each event record once?
One idea is to use select distinct event.* How efficient is that for a large number of fields and records?
Note that the example tables are oversimplified. Each table has MANY more fields and MANY more records.
You can try to use Group BY
select event.event_id, event.event_name from event
join event_performer
on event.event_id = event_performer.event_id
and performer_id in (1,2)
GROUP BY event_name, event.event_id
order by event_name
However do note that if you have created an index on your column then using GROUP BY is similar to using DISTINCT. But if you have not created an index then I would recommend you to go with using DISTINCT as it is comparatively faster than GROUP BY.
I'm trying to get the top 3 interests of each user, probably as a LEFT JOIN query.
The way the app is designed, each user has a set of interests which are no other than 'childs' (rows without parent) of the categories table.
Here are some simplified table schemas w/mock data (see SQL Fiddle demo)
-- Users table
| ID | NAME |
--------------
| 1 | John |
| 2 | Mary |
| 3 | Chris |
-- Categories table -- Interests table
| ID | NAME | PARENT | | ID | USER_ID | CATEGORY_ID |
-------------------------------------- ------------------------------
| 1 | Web Development | (null) | | 1 | 1 | 1 |
| 2 | Mobile Apps | (null) | | 2 | 1 | 1 |
| 3 | Software Development | (null) | | 3 | 1 | 1 |
| 4 | Marketing & Sales | (null) | | 4 | 2 | 1 |
| 5 | Web Apps | 1 | | 5 | 2 | 1 |
| 6 | CSS | 1 | | 6 | 3 | 1 |
| 7 | iOS | 2 | | 7 | 3 | 1 |
| 8 | Streaming Media | 3 | | 8 | 3 | 1 |
| 9 | SEO | 4 |
| 10 | SEM | 4 |
To get the top 3 interests of a given user, I've usually performed this query:
SELECT `c`.`parent` as `category_id`
FROM `interests` `i` LEFT JOIN `categories` `c` ON `c`.`id` = `i`.`category_id`
WHERE `i`.`user_id` = '2'
GROUP BY `c`.`parent`
ORDER BY count(`c`.`parent`) DESC LIMIT 3
This query returns the top 3 categories (parents) of user with id = 2
I would like to find out how I can query the users table and get their top 3 categories either in 3 different fields (preferred) or as a group_concat(..) in one field
SELECT id, name, top_categories FROM users, (...) WHERE id IN ('1', '2', '3');
Any ideas how I should go about doing this?
Thanks!
First build a groped query that lists on distinct rows, the top three skills for each user. Then pivot that into to pull the three skills for eah user out to the right. You will need to use the Max(isnull(skill,'')) expression on the skills in each skill column.
It is very crude way of doing it in MYSQL to get top 3 records for each user
SELECT u.id, c.name
FROM
users u,
categories c,
(SELECT i.id,
i.user_id,
i.category_id,
#running:=if(#previous=i.user_id,#running,0) + 1 as rId,
#previous:=i.user_id
FROM
(SELECT * FROM intersect ORDER BY user_id) i JOIN
(SELECT #running=0, #previous=0 ) r) i
WHERE
u.id = i.USER_ID AND
i.CATEGORY_ID = c.id AND
i.rId <= 3
group by u.id, c.name ;
Hope it helps
FIDDLE
Given a join table for m-2-m relationship between booth and user
+-----------+------------------+
| booth_id | user_id |
+-----------+------------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 5 |
| 1 | 9 |
| 2 | 1 |
| 2 | 2 |
| 2 | 5 |
| 2 | 10 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 3 | 6 |
| 3 | 11 |
+-----------+------------------+
How can I get a distinct set of booth records that are common between a subset of user ids? For example, if I am given user_id values of 1,2,3, I expect the result set to include only booth with id 3 since it is the only common booth in the join table above between all user_id's provided.
I'm hoping I'm missing a keyword in MySQL to accompish this. The furthest I've come so far is using ... user_id = all (1,2,3) but this is always returning an empty result set (I believe I understand why it is though).
The SQL query for this will be:
select booth_id from table1 where [user_id]
in (1,2,3) group by booth_id having count(booth_id) =
(select count(distinct([user_id])) from table1 where [user_id] in (1,2,3))
If this could help you creating the MySQL query.