How to select limited data per category [duplicate] - mysql

This question already has answers here:
Using LIMIT within GROUP BY to get N results per group?
(14 answers)
Closed 3 years ago.
I have a table named Category like
Id Name
1 A
2 B
And i have product table like
Id Name Category_id
1 C 1
2 D 1
3 E 1
4 F 2
5 G 2
6 H 2
I want to select 2 items from each category. I am applying this query
Select Product.id,Product.name as pname,category.name as cname from product join category where Category_id=Category.id limit 0,4
But it's returning first four data of the product table like
Product.id Pname Cname
1 C A
2 D A
3 E A
4 F B
But i Want to get 2 product from each category
Product.id Pname Cname
1 C A
2 D A
4 F B
5 G B

If you are running MySQL 8.0, you can use row_number():
select p.id pid, name, p.name pname, c.name cname
from (
select p.*, row_number() over(partition by category_id order by id) rn from product p
) p
inner join category c on c.id = p.category_id
where p.rn <= 2

Related

mysql count children of selected rows having selected rows as parent?

Table structure(representative)
ID NAME PARENT
--------------------
1 cat1 0
2 cat1 1
3 cat2 1
4 cat1 2
5 cat2 2
6 cat3 2
7 cat1 3
8 cat2 3
9 cat3 3
10 cat1 1
FOREIGN TABLE data for foreign_sub_category_count
id_parent name
-----------------------
2 a
2 b
2 c
3 a
3 b
3 c
categories may have sub categories.
SELECT t.name,t.id
FROM TABLE_NAME AS t
WHERE t.parent = SOME_ID
SOME_ID = 1
gives me the name,id of all categories with SOME_ID parent id
what i want is to get a count of all sub categories of each row in above result set besides the name
WHERE t.id is parent of sub categories and get count of categories from another table which has the same t.id as parent
EXPECTED RESULT
t.id t.name sub_category_count foreign_sub_category_count
2 cat1 3 3
3 cat2 3 3
10 cat1 0 0
I suspect that you are looking for a recursive query - available in MySQL 8.0:
with recursive cte as (
select id root_id, id from mytable
union all
select c.root_id, t.id from cte c inner join mytable t on t.parent = c.id
)
select
t.*,
(select count(*) - 1 from cte c where c.root_id = t.id) no_children
from mytable t
This adds one column to your original table, which contains the number of direct and indirect descendants of the current row.
Try this:
select
tab1.id,
tab1.name,
coalesce(tab2.counts,0) as sub_category_count,
coalesce(tab3.counts,0) as foreign_sub_category_count
from
(select id,name,parent from representative) tab1
left join
(select t1.parent tab_id, count(*) as counts from representative t1 inner join representative t2 on t1.parent=t2.id group by t1.parent) tab2
on tab1.id=tab2.tab_id
left join
(select parent_id,count(*) as counts from foreign_table group by parent_id) tab3
on tab1.id=tab3.parent_id
where tab1.parent=1 --SOME_ID
you can change the parent_id in where tab1.parent=1 of you choice
Example on DB-FIDDLE

sql group by although there is not value

I have a table where exists 4 entries like this.
class_type
id type
1 A
2 B
3 M
4 T
and another table where these values are foreign key.
id number id_class_type
1 10 1
2 11 1
3 12 2
4 13 1
5 14 2
6 15 3
7 16 1
8 17 3
So what i want is count(*) and group by id_class_type but with all class_type (1,2,3,4) although there is not present the id 4.
if you want only the class tha match you can use inner join
select a.class_type, count(*)
from class_type a
inner join table2 b on a.id = b.id_class_type
group by a.class_type
otherwise you can use left join
select a.class_type, count(*)
from class_type a
left join table2 b on a.id = b.id_class_type
group by a.class_type

mysql-display different columns from multiple tables

Consider the following table and values..i need to display all the column and its values from table "TAG" along with single column value from another table named as "ITEM"
TABLE NAME "TAG"
TAGID NAME RATE
1 A 100
2 B 200
3 C 300
4 D 8099
5 E 400
6 F 500
7 G 600
8 H 700
9 I 200
10 J 400
TABLE NAME "ITEM"
ITEMID Name ITEM_QTY
1 A 11
2 B 22
3 I 3
4 A 8
5 B 42
6 C 5
7 I 61
8 B 74
9 C 99
10 A 48
EXPECTED OUTPUT
TAGID NAME RATE ITEM_QTY
1 A 100 48 - (VALUE OF LAST INSERTED RECORD)
2 B 200 74
3 C 300 99
4 D 8099 0
5 E 400 0
6 F 500 0
7 G 600 0
8 H 700 0
9 I 200 61
10 J 400 0
i have tried some sort of quires but its all vien..
this is my query,
select *
from tag t1
join ( select item_qty
from item t2
join tag t1
on t1.name=t2.name;
can anyone pls help me out of this issue...
thanks in advance...
try like this
select tag.id,tag.name,rate,qty from tag join
(select qty,name from
ITEM where ITEM.id in
(select max(id) from ITEM group by name)) as tt on tt.name=tag.name
Assuming, that the last inserted record has the highest ID in your item table, you first need to get the highest ID per item name.
SELECT
Name, MAX(ITEMID) AS max_id
FROM
item
GROUP BY Name;
With this query (executed in the following query as subquery) we get the corresponding row for each max_id.
SELECT i.*
FROM item i
JOIN (
SELECT
MAX(ITEMID) AS max_id
FROM
item
GROUP BY Name
) si ON i.ITEMID = si.max_id;
Here are more examples of how to get The Rows Holding the Group-wise Maximum of a Certain Column.
The final query is
SELECT TAGID, tag.NAME, RATE, COALESCE(ITEM_QTY, 0) AS ITEM_QTY
FROM
tag
LEFT JOIN (
SELECT i.*
FROM item i
JOIN (
SELECT
MAX(ITEMID) AS max_id
FROM
item
GROUP BY Name
) si ON i.ITEMID = si.max_id
) items ON tag.Name = items.Name
see it working live in an sqlfiddle
You may try as
select
t.tagid,
t.name,
t.rate,
i.item_qty
from tag t
join
(
select name,max(item_qty) as item_qty
from item group by name
)i
on i.name = t.name
DEMO
If you need all the data from item table as you have shown in the output you may use left join instead of inner join
select
t.tagid,
t.name,
t.rate,
coalesce(i.item_qty,0) as item_qty
from tag t
left join
(
select name,max(item_qty) as item_qty
from item group by name
)i
on i.name = t.name
DEMO

Join with limit on right table

Say I have two tables I want to join.
Categories:
id name
----------
1 Cars
2 Games
3 Pencils
4 Books
And items:
id categoryid itemname
---------------------------
1 1 Ford
2 1 BMW
3 1 VW
4 2 Tetris
5 2 Pong
6 3 Foobar Pencil Factory
I want a query that returns the category and the last maximum N (for example: 2) itemname:
category.id category.name item.id item.itemname
-------------------------------------------------
1 Cars 2 BMW
1 Cars 3 VW
2 Games 4 Tetris
2 Games 5 Pong
3 Pencils 6 Foobar Pencil Factory
4 Books NULL NULL
I want write a query like below:
Select * From categories c
Left Join (select * from items order by id desc) i
On c.id=i=categoryid
AND LIMIT 2 #comment: N=2 this line not supported
Where i.categoryid = c.id
Group By c.id
Thanks!
I'm not saying it's efficient, but it should work:
SELECT c.*, i.id, i.itemname
FROM categories c
LEFT JOIN
(SELECT i.*
FROM items i
LEFT JOIN items i2 ON i.categoryid = i2.categoryid AND i2.id > i.id
GROUP BY i.id
HAVING COUNT(*) < 2 # this 2 = N
) i ON c.id = i.categoryid
Check http://sqlfiddle.com/#!2/9a132/1
SELECT *
FROM Categories c
LEFT JOIN -- Items i
(
SELECT * FROM Items WHERE LOCATE(id,
(
SELECT GROUP_CONCAT(it.itemids) AS its
FROM (
SELECT (SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8))
ORDER BY id DESC), ',', 2)) AS itemids
FROM Items
GROUP BY categoryid
) it
)) <> 0
) i
ON i.categoryid = c.id;
where N=2 is: SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8)) ORDER BY id DESC), ',', 2)
Because GROUP_CONCAT is by default sort ASC ; above will become SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8)) ), ',', -2). But GROUP_CONCAT result is truncated to max len 1024 (group_concat_max_len).

How To write a SQL Select Query for this problem?

I have four tables: groups, users, votes, follows.
The structures of these tables are
groups
g_id g_title g_content
1 t1 content1
2 t2 content2
users
u_id u_groupid
1 1
2 1
3 2
4 2
5 2
votes
v_id v_userid v_groupid v_votes
1 1 1 1
2 1 2 1
3 2 2 1
4 3 2 1
5 3 1 1
follows
f_id f_userid f_groupid
1 1 1
2 2 1
3 2 2
4 3 1
5 3 2
The groups table records the basic information of a "group".
The users table keeps the relationship between users and groups, that is, if the user A belongs to groups B, then there will be a record in the user table.
The votes table means the supportive attitude that a user holds to a group.
If user A is interested in group A, then add a entry into the Follows table.
Now my problem is how to write one select statement to query the number of users, the number of votes and the number of followers of each group.
I want the query result likes this
g_id num_users unm_votes num_followers
1 2 2 3
2 3 3 2
By the way, my database is Mysql 5.0.51b.
If you want in 1 query, something like this will help you
SELECT g_id,
d1.num_users,
d2.unm_votes,
d3.num_followers
FROM groups gg
LEFT JOIN (SELECT g_id,
COUNT(u.u_id) AS num_users
FROM groups g
LEFT JOIN users u
ON u.u_groupid = g.g_id
GROUP BY g_id) d1
ON d1.g_id = gg.g_id
LEFT JOIN (SELECT g_id,
COUNT(v.v_userid) AS unm_votes
FROM groups g
LEFT JOIN votes v
ON v.v_groupid = g.g_id
GROUP BY g_id) d2
ON d2.g_id = gg.g_id
LEFT JOIN (SELECT g_id,
COUNT(f.f_userid) AS num_followers
FROM groups g
LEFT JOIN follows f
ON f.f_groupid = g.g_id
GROUP BY g_id) d3
ON d3.g_id = gg.g_id
GROUP BY gg.g_id
For the user count by group:
select g_id,count(u.uid) user_count from groups g, users u
where u.groupid = g.g_id
group by g_id
May want to read up on group by.