how to select 3 random items of each category? - mysql

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);

Related

The best way to Find entries missing after inner-join?

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

SQL COUNT DISTINCT values tied to record via JOIN

I have 2 tables:
stock
StockID | ItemName
1 | hat
2 | hammer
3 | banana
4 | elephant
5 | book
and Basket
BasketID | StockID | Quantity
1 | 3 | 5
2 | 2 | 20
3 | 1 | 7
4 | 2 | 60
5 | 5 | 23
6 | 1 | 17
7 | 3 | 3
8 | 4 | 6
9 | 3 | 1
10 | 2 | 1
11 | 2 | 13
I'm trying to make an SQL query which out puts the StockID, ItemName, Total Quantity Sold, and the Number of Orders that Item had.
I have this:
SELECT stock.StockID, stock.ItemName, SUM( basket.Quantity ) AS QuantitySold
FROM stock
JOIN basket ON stock.StockID = basket.StockID
GROUP BY stock.Itemname
ORDER BY stock.StockID
LIMIT 0 , 30
Which works fine, but when I try adding:
COUNT (DISTINCT basket.BasketID)
I just get a message saying I have a Syntax Error.
I am fairly new to all this, so sorry if my logic is wrong, but shouldn't that just count the distinct values tied to stockID, as it does pretty much that with the SUM of quantity sold, where it locates all the basket.Quantity values tied to the stockID in the basket table.
All help much appreciated -Tom
Not sure if this is the full answer to your question, but I don't think that in MySQL you can have a space between the function name and the leading parenthesis like you do with COUNT.

How to select only that what matches all parameters in many-to-many

Need to get only the records that match all the specified conditions in many-to-many relationship.
Greatly simplified tables look like
Catalog Catalog_Types Types
1 1 1 1
2 1 2 2
3 2 1 3
2 3 4
2 4
3 1
3 4
It easy to select from Catalog by 1 type, but i need select by 1 ore more, for example how to get from Catalog only those rows that have Types 1 and 2, so if it have 1 but haven't 2 it is not suitable.
I saw a similar question and the decision here, but for the SQL. There used except, i tried to replace it by equals on mySQL, but I do not know mySQL so well.
thank you in advance,
and sorry for my english
This type of query is called "set within set"
If you want to get catalog ids with two types (1 and 2) but may have other types
SELECT catalog_id
FROM catalog_type
WHERE type_id IN (1, 2)
GROUP BY catalog_id
HAVING COUNT(DISTINCT type_id) = 2
if want to make sure you get catalog ids with exactly two types (e.g. 1 and 2)
SELECT catalog_id
FROM catalog_type
GROUP BY catalog_id
HAVING SUM(type_id = 1) > 0
AND SUM(type_id = 2) > 0
AND COUNT(DISTINCT type_id) = 2;
if you want to get catalog ids which have at least two of three types (e.g. 1, 2, 4)
SELECT catalog_id
FROM catalog_type
WHERE type_id IN (1, 2)
GROUP BY catalog_id
HAVING (MAX(type_id = 1)
+ MAX(type_id = 2)
+ MAX(type_id = 4)) >= 2
Assuming that you have following in catalog_type
| CATALOG_ID | TYPE_ID |
------------------------
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 3 | 4 |
Sample output for above-mentioned queries:
query 1 query 2 query 3
| CATALOG_ID | | CATALOG_ID | | CATALOG_ID |
-------------- -------------- --------------
| 1 | | 1 | | 1 |
| 3 | | 3 |
Here is SQLFiddle demo for all these queries. Take a look and see how results differ.

Remove duplicates from one column keeping whole rows

id | userid | total_points_spent
1 | 1 | 10
2 | 2 | 15
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
With the above table, I would first like to remove duplicates of userid keeping the rows with the largest total_points_spent, like so:
id | userid | total_points_spent
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
And then I would like to sum the values of total_points_spent, which would be the easy part, resulting in 70.
I am not really sure the "remove" you meant is to delete or to select. Here is the query for select only max totalpointspend record respectively.
SELECT tblA.*
FROM ( SELECT userid, MAX(totalpointspend) AS maxtotal
FROM tblA
GROUP BY userid ) AS dt
INNER JOIN tblA
ON tblA.userid = dt.userid
AND tblA.totalpointspend = dt.maxtotal
ORDER BY tblA.userid

INNER JOIN DISTINCT with MySQL

I have a mysql problem. I have two tables like this that I need to join together.
table:
id otherid2
1 | 1
2 | 1
3 | 2
4 | 2
table2:
otherid otherid2
1 | 1
2 | 1
3 | 2
4 | 2
I'm using:
SELECT id,otherid FROM table INNER JOIN table2 ON table.otherid2=table2.otherid2
This gives me:
id otherid
1 | 1
1 | 2
2 | 1
2 | 2
3 | 3
3 | 4
4 | 3
4 | 4
As you can see I get duplicates of id as there is otherid2s that is not unique in table2. What I need is to INNER JOIN DISTINCT in some way, I only want the result to be as below. Not duplicates.
This is what I want:
id otherid
1 | 1
2 | 1
3 | 3
4 | 3
Can I do this in an easy way?
If you want the row with the lowest id in table2, this should probably do it
SELECT id, min(otherid)
FROM table
INNER JOIN table2
ON table.otherid2=table2.otherid2
GROUP BY id
In your comment you wanted the lowest, then I'd suggest a group by and a min aggregator
SELECT id, MIN(otherid) AS otherid ... GROUP BY id