Lets suppose that we have the following 3 tables
Animal
id name
1 dog
2 cat
3 crow
Actions
id name
1 run
2 walk
3 jump
4 fly
5 puppy_eyes
6 swim
Animal_Actions
id Animal_id action_id
1 1 1
2 1 2
3 1 3
4 1 5
5 2 1
6 2 2
7 2 3
8 3 2
9 3 4
I would like to find all the missing animal actions for certain animals
For example if we input dog and cat( id 1 and 2) we should get the following (1,4),(1,6),(2,4),(2,5), (2,6)
and if we input crow (3) we get the following (3,1),(3,3),(3,5), (3,6) .
Currently I'm doing an inner join between Animal and Animal_Actions table based on animal ID and importing this into a SET in my code and checking if every possible permutation is present in this set and collecting the missing ones. I'm not sure if the process I follow is the most efficient one, is there a better way to do this when the data is at a large scale ? Thanks in advance.
If you'll be filtering on a small number of Animal records, one approach is to do a CROSS JOIN with the Actions table. That will give you all action combinations for each Animal record. Then do an OUTER JOIN to Animal_Actions to identify which ones are missing.
For example, using cat = 2 and dog = 1
SELECT ani.id AS Animal_Id
, ani.Name AS Animal_Name
, act.id AS Action_Id
, act.Name AS Action_Name
FROM Animal ani
CROSS JOIN Actions act
LEFT JOIN Animal_Actions aa ON ani.id = aa.Animal_id
AND aa.Action_Id = act.id
WHERE ani.id IN (1,2)
AND aa.id IS NULL
ORDER BY ani.Name, act.Name
;
Results:
Animal_Id | Animal_Name | Action_Id | Action_Name
--------: | :---------- | --------: | :----------
2 | cat | 4 | fly
2 | cat | 5 | puppy_eyes
2 | cat | 6 | swim
1 | dog | 4 | fly
1 | dog | 6 | swim
db<>fiddle here
Related
I have the table followers that looks like this:
id |follower_id|followee_id|
1 | 1 | 2 |
2 | 1 | 3 |
2 | 1 | 4 |
3 | 2 | 3 |
4 | 2 | 4 |
5 | 3 | 2 |
6 | 4 | 6 |
Where follower is a user_id and followee is the user they follow.
How can I find the users that have the most common followees with let's say user 1?
The results need to be ordered by number of common followees.
For example for the current table the results for user 1 would be:
follower_id|common_followees|
2 | 2 |
3 | 1 |
As you can see 4 does not appear in results since it has no common followees with user 1
I hope I explained the problem right.
Thank You.
This is a self-join and aggregation:
select f.follower_id, count(*) as num_common_followees
from followers f join
followers f1
on f.followees = f1.followees and f1.follower_id = 1
group by f.follower_id;
You can add where f.follower_id <> 1. I like to leave that row in as a validation check.
I have 2 tables, animal and people, I am making a query using UNION to get a combined list of both tables, but I want every 4 animals I look 1 person, that is:
Results:
*animal 1
animal 2
animal 3
animal 4*
**person 1**
*animal 5
animal 6
animal 7
animal 8*
**person 2**
etc...
Is there any way to do it?
Please help me!
DEMO: using rextester
Using user variables you can often simulate analytics in enterprise databases (though not nearly as efficient)
We generate derived table (UnionSeq) to generate the needed sequencing and then add our own formula to multiply the generated row_number for persons to be 4 * greater so it will fit in after the 4th animal and use column aliased seq to determine that animals come before people in the order. Then we select from the derived table to apply the needed ordering.
SELECT Name
FROM (SELECT ID, Name, (#p:=#P+1)*4 Row_num, 'b' as Seq
FROM person
CROSS JOIN (SELECT #p:=0) a
UNION ALL
SELECT ID, Name, #a:=#a+1, 'a' as seq
FROM animal
CROSS JOIN (SELECT #a:=0) b) UnionSeq
ORDER BY Row_num, Seq
Giving us:
+----+----------+
| | Name |
+----+----------+
| 1 | Animal 1 |
| 2 | Animal 2 |
| 3 | Animal 3 |
| 4 | Animal 4 |
| 5 | Person 1 |
| 6 | Animal 5 |
| 7 | Animal 6 |
| 8 | Animal 7 |
| 9 | Animal 8 |
| 10 | Person 2 |
| 11 | Animal 9 |
| 12 | Person 3 |
+----+----------+
Your sample data doesn't show what to do if there are disproportionate numbers of people to animals; so in my demo I just let each table show all data based on a pattern irrespective if the 4x1 pattern can't be maintained. In this example you can see Animal 9 is followed by person 3 even though there aren't 4 animals. and if there was a person 4 it would follow person 3 as there would be no more animals.
It's not magic; it's math and general SQL processes and order of operations.
I am facing a conundrum; not sure why -- is it because this late, or I am just stuck. My goal is to create a filter on the webpage, so I am trying to figure this out.
I have a list of products that I store with filters in the reference table product_filter.
The structure:
id | product_id | filter1_id | filter2_id
1 | 1 | 2 | 1 <---
2 | 1 | 4 | 3
3 | 1 | 5 | 1
4 | 2 | 2 | 1 <---
5 | 2 | 3 | 1
6 | 3 | 2 | 1 <---
7 | 3 | 3 | 4
I need to submit a list of products (for example 1,2,3) and get only those filter combinations, that are the same for all selected product id's. So the result needs to be
filter1_id | filter2_id
2 | 1
My problem is that my products might vary and I can't do a ton of self inner joins... so I am stuck... Any advise?
Here is one approach that you could try:
select filter1_id, filter2_id
from product_filter
group by filter1_id, filter2_id
having count(*)=(
select count(distinct product_id)
from product_filter
)
This will only return a list when a combination of filter1_id and filter2_id exists for every product_id. (Fiddle here.) Is that what you are after? Do you don't mention what should be returned if there isn't any combination that exists for all of the given product_id's - an empty result set?
It's not a self-join (or even a ton of them ;) ) but it will still be fairly expensive I imagine.
I have two tables that I'm attempting to retrieve specific information from (duh I know). The first table seasons is semi-static data storage and the second table users_cards is used to store user choices.
The result I am hoping to achieve would go through each season, assign a "card_total" = 10 for seasons 1-3 and 11 for each season moving forward. The result would look something similar to:
SEASON_ID | TOTAL |
------------ ------------
1 | 123
2 | 234
3 | 345
4 | 456
The abbreviated & pertinent columns / sample data is as follows:
# `seasons`:
ID | ACTIVE | COMPLETE |
---- ----------- ---------------
1 | 0 | 1
2 | 0 | 1
3 | 0 | 1
4 | 1 | 0
5 | 0 | 0
# `users_cards`
# DESC: this table can store up to 10 choices per user for seasons 1-3
# and up to 11 choices for every season thereafter.
USER_ID | SEASON_ID |
------------ ---------------
1 | 1
1 | 1
2 | 1
2 | 1
1 | 2
1 | 2
1 | 2
I've played around with a few variations of this query but nothing seems to be doing the trick. This query returns the total count for each season but it's not based off of the "card_total" I mentioned above.
SELECT
c.season_id AS season_id,
c.card_total AS card_total,
c.total AS total
FROM seasons s
INNER JOIN (
SELECT
uc.season_id,
COUNT(DISTINCT(user_id)) AS total,
CASE WHEN
uc.season_id = 1
OR uc.season_id = 2
OR uc.season_id = 3
THEN 10
ELSE 11
END AS card_total
FROM users_cards uc
GROUP BY uc.season_id
) AS c ON c.season_id = s.id
WHERE s.is_active = 1
OR s.is_complete = 1
Put SUM() around your CASE...END.
I need some help writing a select query basically I have the table structured as below:
cat_prod
----------
cid | pid
----------
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
1 | 2
2 | 3
3 | 4
4 | 5
5 | 1
1 | 3
2 | 4
3 | 5
4 | 1
5 | 2
Now I would like to select at least 3 random pid's of each cid where it exists or the maximum pid's if less than 3, how would i do that in one query? Baring in mind I would like the query to be as efficent as possible and that the table data is likely to grow considerablly.
Thanks
Although some changes might be needed, the following query is almost appropriate:
select C.cid, C.pid
from cat_prod C
where C.pid in (select c1.pid from cat_prod c1 order by (pid) limit 3);