mysql retrive data giving limit and sub limit - mysql

I have a table named item with category ID and item IDs.
Item ID is the primary key and each item is related to category ID.
I want to retrieve 20 items, but 4 items for one category. If there aren't 4 items for
some category, then select all items from this category.
This is my query, it is not working:
SELECT * FROM `item`
JOIN (SELECT `item_id` FROM `item` GROUP BY `category_id` LIMIT 4) LIMIT 20;
my table stucture
item
item id | category id
----------------------------
1 | 1
2 | 1
3 | 2
4 | 2
5 | 1
6 | 3
if my table has
category
category | count(item)
-----------------------------
1 | 5
2 | 3
3 | 10
4 | 8
5 | 12
6 | 6
7 | 6
8 | 6
I want to select 20 items like that
category items from this category
----------
1 | 4
2 | 3
3 | 4
4 | 4
5 | 4
6 | 1

You can try this query
SET #level = 0;
SET #group = '';
SELECT
item_id,
category_id
FROM (
SELECT
item_id,
category_id,
#level := IF(#group = category_id, #level+1, 1) AS level,
#group := category_id as EGroup
FROM item
ORDER BY category_id
) rs
WHERE level < 5
Here is some sample data
| ID | ITEM_ID | CATEGORY_ID |
|----|---------|-------------|
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 4 | 1 |
| 5 | 5 | 1 |
| 6 | 6 | 2 |
| 7 | 7 | 2 |
| 8 | 8 | 2 |
| 9 | 9 | 2 |
| 10 | 10 | 3 |
| 11 | 11 | 3 |
| 12 | 12 | 3 |
| 13 | 13 | 3 |
| 14 | 14 | 3 |
| 15 | 15 | 3 |
| 16 | 16 | 4 |
| 17 | 17 | 4 |
| 18 | 18 | 5 |
| 19 | 19 | 5 |
| 20 | 20 | 5 |
| 21 | 21 | 5 |
| 22 | 22 | 5 |
| 23 | 23 | 6 |
| 24 | 24 | 7 |
| 25 | 25 | 7 |
Output
| ITEM_ID | CATEGORY_ID |
|---------|-------------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 9 | 2 |
| 8 | 2 |
| 7 | 2 |
| 6 | 2 |
| 15 | 3 |
| 14 | 3 |
| 13 | 3 |
| 12 | 3 |
| 16 | 4 |
| 17 | 4 |
| 22 | 5 |
| 21 | 5 |
| 20 | 5 |
| 19 | 5 |
| 23 | 6 |
| 24 | 7 |
| 25 | 7 |
SQL Fiddle Demo

Related

MySQL: How to select (count renewal bookings & count of all bookings) for each room?

+----+---------+---------+
| id | room_id | user_id |
+----+---------+---------+
| 1 | 5 | 10 |
| 2 | 5 | 20 |
| 3 | 5 | 20 |
| 4 | 6 | 30 |
| 5 | 6 | 40 |
| 6 | 6 | 50 |
| 7 | 7 | 10 |
| 8 | 7 | 10 |
| 9 | 8 | 20 |
| 10 | 9 | 10 |
| 11 | 9 | 10 |
| 12 | 9 | 10 |
+----+---------+---------+
I want to select top rooms with count bookings and with count of renewal bookings for each room
To get this result
+---------+----------------+---------------+
| room_id | total_bookings | total_renewal |
+---------+----------------+---------------+
| 5 | 3 | 1 |
| 6 | 3 | 0 |
| 7 | 2 | 1 |
| 8 | 1 | 0 |
| 9 | 3 | 2 |
| 5 | 1 | 0 |
+---------+----------------+---------------+
And this live mysql here
https://paiza.io/projects/Ao2C6d6pgE133QXQAl03Ug?language=mysql
........
Considering your requirement for renewal is not clear, something like this could do the job, using pure sql:
select
s.room_id,
sum(s.total_bookings) as total_bookings,
sum(case when s.total_bookings > 1 then s.total_bookings - 1 else 0 end) as total_renewal
from (
select room_id, user_id, count(*) as total_bookings
from booking
group by room_id, user_id
) s
group by s.room_id;

How to compare a new value to last value in the table

I am trying to create a trigger in MySQL database. I have a table (myData) with 3 columns. Date, Values, and Status. What I am trying to achieve is, when a new value comes, if it is higher than the last value, It should insert 1 in the Status column. If it is less than the last value, It should insert 0 in the status column. I couldn't find a logic to do it. Any suggestions, please?
BEGIN
IF new.Values > // what should be here?
THEN
INSERT INTO //
END
Instead consider the following:
SELECT * FROM my_table;
+----+-------+
| id | value |
+----+-------+
| 1 | 2 |
| 2 | 12 |
| 3 | 13 |
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 7 | 8 |
| 8 | 3 |
| 9 | 10 |
| 10 | 1 |
| 11 | 18 |
| 12 | 4 |
| 13 | 6 |
| 14 | 0 |
| 15 | 2 |
| 16 | 8 |
| 17 | 14 |
| 18 | 7 |
| 19 | 15 |
| 20 | 11 |
| 21 | 12 |
| 22 | 7 |
| 23 | 20 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 28 | 12 |
| 29 | 3 |
| 30 | 18 |
| 31 | 1 |
| 32 | 12 |
+----+-------+
SELECT a.*
, b.value >= a.value n
FROM my_table a
LEFT
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id;
+----+-------+------+
| id | value | n |
+----+-------+------+
| 1 | 2 | NULL |
| 2 | 12 | 0 |
| 3 | 13 | 0 |
| 4 | 9 | 1 |
| 5 | 7 | 1 |
| 6 | 6 | 1 |
| 7 | 8 | 0 |
| 8 | 3 | 1 |
| 9 | 10 | 0 |
| 10 | 1 | 1 |
| 11 | 18 | 0 |
| 12 | 4 | 1 |
| 13 | 6 | 0 |
| 14 | 0 | 1 |
| 15 | 2 | 0 |
| 16 | 8 | 0 |
| 17 | 14 | 0 |
| 18 | 7 | 1 |
| 19 | 15 | 0 |
| 20 | 11 | 1 |
| 21 | 12 | 0 |
| 22 | 7 | 1 |
| 23 | 20 | 0 |
| 24 | 17 | 1 |
| 25 | 8 | 1 |
| 26 | 6 | 1 |
| 27 | 6 | 1 |
| 28 | 12 | 0 |
| 29 | 3 | 1 |
| 30 | 18 | 0 |
| 31 | 1 | 1 |
| 32 | 12 | 0 |
+----+-------+------+
If all you want is the rows where n=1, then the query is actually even simpler...
SELECT a.*
FROM my_table a
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id
AND b.value >= a.value;
+----+-------+
| id | value |
+----+-------+
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 8 | 3 |
| 10 | 1 |
| 12 | 4 |
| 14 | 0 |
| 18 | 7 |
| 20 | 11 |
| 22 | 7 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 29 | 3 |
| 31 | 1 |
+----+-------+

How to select multiple values for one table "cell" MySQL

For all players, I need to find the player number and a list of the numbers of teams for which they have ever played.
Here is the table "MATCHES":
+---------+--------+----------+-----+------+
| MATCHNO | TEAMNO | PLAYERNO | WON | LOST |
+---------+--------+----------+-----+------+
| 1 | 1 | 6 | 3 | 1 |
| 2 | 1 | 6 | 2 | 3 |
| 3 | 1 | 6 | 3 | 0 |
| 4 | 1 | 44 | 3 | 2 |
| 5 | 1 | 83 | 0 | 3 |
| 6 | 1 | 2 | 1 | 3 |
| 7 | 1 | 57 | 3 | 0 |
| 8 | 1 | 8 | 0 | 3 |
| 9 | 2 | 27 | 3 | 2 |
| 10 | 2 | 104 | 3 | 2 |
| 11 | 2 | 112 | 2 | 3 |
| 12 | 2 | 112 | 1 | 3 |
| 13 | 2 | 8 | 0 | 3 |
+---------+--------+----------+-----+------+
The best I could come up with was:
SELECT DISTINCT playerno, teamno
FROM matches
ORDER BY playerno;
which results in:
+----------+--------+
| playerno | teamno |
+----------+--------+
| 2 | 1 |
| 6 | 1 |
| 8 | 1 |
| 8 | 2 |
| 27 | 2 |
| 44 | 1 |
| 57 | 1 |
| 83 | 1 |
| 104 | 2 |
| 112 | 2 |
+----------+--------+
Notice how player 8 has played on two teams. How can I get the table to show only one row for player 8 and a list of teamno's (1 & 2)?
You could use the group_concat aggregate function:
SELECT playerno, GROUP_CONCAT(DISTINCT teamno)
FROM matches
GROUP BY playerno
ORDER BY playerno;
You could use group_concat
SELECT playerno, group_concat( teamno)
FROM matches
GROUP BY playerno;

mysql distinct column on multiple row conditions

I have a mysql database (item_preset) with the following table:
+-----+-----------+---------+-------+
| id | preset_id | item_id | value |
+-----+-----------+---------+-------+
| 1 | 1 | 1 | 2 |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 4 | 60 |
| 4 | 1 | 3 | 16 |
| 5 | 1 | 3 | 17 |
| 6 | 1 | 3 | 18 |
| 7 | 1 | 3 | 25 |
| 8 | 1 | 3 | 26 |
| 9 | 1 | 3 | 27 |
| 10 | 2 | 1 | 3 |
| 11 | 2 | 2 | 0 |
| 12 | 2 | 4 | 0 |
| 13 | 2 | 3 | 16 |
| 14 | 2 | 3 | 17 |
| 15 | 2 | 3 | 19 |
| 16 | 2 | 3 | 20 |
| 17 | 2 | 3 | 21 |
| 18 | 3 | 1 | 2 |
| 19 | 3 | 2 | 0 |
| 20 | 3 | 4 | 0 |
| 21 | 3 | 3 | 25 |
| 22 | 3 | 3 | 28 |
| 23 | 4 | 1 | 1 |
| 24 | 4 | 2 | 1 |
| 25 | 4 | 4 | 120 |
| 26 | 4 | 3 | 16 |
| 27 | 4 | 3 | 17 |
| 28 | 4 | 3 | 18 |
| 29 | 4 | 3 | 22 |
| 30 | 4 | 3 | 23 |
| 31 | 4 | 3 | 24 |
| 32 | 6 | 1 | 3 |
| 33 | 6 | 2 | 1 |
| 34 | 6 | 4 | 90 |
| 35 | 6 | 3 | 18 |
| 36 | 6 | 3 | 22 |
| 37 | 6 | 3 | 23 |
| 38 | 6 | 3 | 24 |
| 39 | 6 | 3 | 29 |
| 40 | 6 | 3 | 30 |
+-----+-----------+---------+-------+
What I would like to do is get the distinct preset_id based on conditions from multiple rows.
eg to get preset_id 1 i need all the conditions to be true (item_id = 1 and value_id = 2), (item_id = 2 and value = 1), etc...
I have tried usintg the following:
select distinct preset_id from item_preset where (item_id = 1 and value = 2) and (item_id = 2 and value = 1) and (item_id = 4 and value = 60);
but get an Empty Set. If I try with Or's instead of and I get all preset_ids that match any of the conditions.
Any Ideas?
Thanks
You might want to try this thing,
SELECT preset_id
FROM tableName
WHERE (item_id = 1 and value = 2) OR
(item_id = 2 and value = 1) OR
(item_id = 4 and value = 60)
GROUP BY preset_id
HAVING COUNT(*) = 3
SQLFiddle Demo
You can try something like this:
select distinct preset_id from item_preset
where preset_id in (select preset_id from item_preset where item_id = 1 and value = 2)
and preset_id in (select preset_id from item_preset where item_id = 2 and value = 1)
and preset_id in (select preset_id from item_preset where item_id = 4 and value = 60);
More brackets,
select distinct(preset_id) from item_preset where ((item_id = 1 and value = 2) or (item_id = 2 and value = 1) or (item_id = 4 and value = 60));
and value is a keyword - don't use value as a column name

join with a group by?

i have a table called rc_language_type_table with:
id language
1 english
2 Xhosa
3 afrikaans
etc
then i have a table rc_language_type_assoc_table with:
profile_id | language_type_id |
+------------+------------------+
| 3 | 1 |
| 13 | 1 |
| 15 | 1 |
| 16 | 1 |
where i have profiles and each profile is connected to a language id in a 1 to many
so then i did:
select *,count(*) from rc_language_type_assoc_table group by language_type_id;
+------------+------------------+----------+
| profile_id | language_type_id | count(*) |
+------------+------------------+----------+
| 3 | 1 | 96 |
| 3 | 2 | 19 |
| 3 | 3 | 18 |
| 64 | 4 | 51 |
| 94 | 5 | 10 |
| 37 | 6 | 26 |
| 3 | 7 | 21 |
| 3 | 8 | 4 |
| 3 | 9 | 6 |
| 88 | 10 | 4 |
| 3 | 11 | 3 |
+------------+------------------+----------+
what i want now is: instead having the language_type_id i want to display the actual language...how would i do this please???
i tried:
select *, count(*)
from rc_language_type_assoc_table, rc_language_type_table
group by language_type_id
where rc_language_type_assoc_table.language_type_id = rc_language_type_table.id;
but i get a syntax error...
please help??
thank you
GROUP BY should be "after" the WHERE statement and not before
select *, count(*)
from rc_language_type_assoc_table, rc_language_type_table
where rc_language_type_assoc_table.language_type_id = rc_language_type_table.id
group by language_type_id ;