In three tables:
Actors:
+------------------+
| id_a | actor_name|
+------------------+
| 1 | AAA |
| 2 | Bbb |
| 3 | Ccc |
| 4 | Ddd |
| 5 | Eee |
+------------------+
Movies:
+----------------+
| id_m | mov_name|
+----------------+
| 1 | LoR |
| 2 | Thron |
| 3 | ZsT |
+----------------+
actors_in_movies:
+-------------+
| id_m | id_a |
+-------------+
| 1 | 1 |
| 1 | 3 |
| 1 | 5 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 3 | 5 |
+-------------+
Is possible to write one query to get: all movies where actors from query play ?
Example: SELECT id_m WHERE id_a IN (1,3,4,5), should give:
+------+
| id_m |
+------+
| 1 |
| 2 |
+------+
however.. SELECT id_m WHERE id_a IN (1,9) should give NULL.
I tried similar queries: Finding ID having all values (mySQL, SQL), writing something like:
SELECT id_m, count(*), group_concat(id_a) as all_act
FROM actors_in_movies
WHERE
id_m IN (SELECT id_m FROM actors_in_movies WHERE id_a = 1)
AND
id_m IN (SELECT id_m FROM actors_in_movies WHERE id_a = 3)
AND
id_m IN (SELECT id_m FROM actors_in_movies WHERE id_a = 5)
GROUP BY (id_m)
HAVING count(*) <= 3
it show only one movie (id_m: 1),
if i use 'OR' it's almost OK,
but it's important to me to get all movies where actors from query play,
quered actors or less, never movies that have actors missed in query.
How it should be written ?
Use group by and having:
SELECT id_m
FROM table
WHERE id_a IN (1, 9)
GROUP BY id_m
HAVING COUNT(DISTINCT id_a) = 2;
Related
I have a table like this with 8 rows
+----+------+------+--------+
| id | type | attr1 | attr2 |
+----+------+-------+-------+
| 1 | a | abcd | qwer |
| 2 | a | efgh | tyui |
| 2 | b | ijkl | opas |
| 3 | a | mnop | dfgh |
| 4 | a | qrst | jklz |
| 5 | a | uvwx | xcvb |
| 5 | b | yzab | nmqw |
| 6 | b | cdef | erty |
+----+------+-------+-------+
It is known than type can be either 'a' or 'b'.
I need to select the rows in such a way that if there are more than one rows with same id, then select the one with type 'a'. Else select the row with whatever type is present.
So my desired result should be like
+----+------+------+--------+
| id | type | attr1 | attr2 |
+----+------+-------+-------+
| 1 | a | abcd | qwer |
| 2 | a | efgh | tyui |
| 3 | a | mnop | dfgh |
| 4 | a | qrst | jklz |
| 5 | a | uvwx | xcvb |
| 6 | b | cdef | erty |
+----+------+-------+-------+
I have a MySQL query
SELECT t.id,
CASE
WHEN count(t.id) > 1 THEN 'a'
ELSE t.type
END `type`
FROM table1 t
GROUP BY t.id
ORDER BY t.type ASC
which gives this result
+----+------+
| id | type |
+----+------+
| 1 | a |
| 2 | a |
| 3 | a |
| 4 | a |
| 5 | a |
| 6 | b |
+----+------+
But I need the respective row with all columns.
How to do that?
Note that the MySQL version that I have is 5.7.12.
You don't mention if multiple a's with the same id are possible or what to do in that case. I'm going to assume you want all a rows included. To do that, you just need to exclude b rows when there is a corresponding a row:
select t.*
from table1 t
left join table1 t2 on t2.id=t.id and t.type='b' and t2.type='a'
where t2.id is null;
you also can do it using window function:
select * from
(
select * , row_number() over (partition by id order by case when type = 'a' then 0 else 1 end) rn
) t
where rn = 1;
Hmmm . . . I would be inclined to use not exists:
select t.*
from t
where t.type = 'a' or
not exists (select 1
from t t2
where t2.id = t.id and t2.type = 'a'
);
i have table1 :
+----+-------+
| id | name |
+----+-------+
| 1 | name1 |
| 2 | name2 |
| 3 | name3 |
| 4 | name4 |
+----+-------+
i have table2 :
+------+---------+----------+
| id | attribut| value |
+------+---------+----------+
| 1 | 1 | 1 |
| 1 | 3 | 3 |
| 2 | 1 | 1 |
| 2 | 3 | 4 |
+------+---------+--------- +
i want to select the distinct id(s) and name(s) in table1 that have ( attribut 1 and value 1) and (attribut 3 and value 3) in table 2
the result will be 1/name1 in this case
thanks for help !!
select * from table1
where id in(select id
from table2
where (attribut, value) in ( (1,1), (3,3) )
group by id
having count(*)=2
)
I'm fairly new to sql. This might be basic. I have two tables one with groups and one with members, I want to link them up so that a third table contains id_group and id_member. The value MYGROUP is supplied during the import. I tried this:
insert ignore into member_group (id_group, id_member)
values ( ( select id_group from group where group_name='MYGROUP' ) ,
( select id_member from member ) );
But I end up with one row in member_group containing a null value.
on it's own this yields 1 for example:
select id_group from group where group_name='MYGROUP';
+----------+
| id_group |
+----------+
| 1 |
+----------+
on it's own this yields a list of id_members
mysql> select id_member from member;
+-----------+
| id_member |
+-----------+
| 123 |
| 456 |
| 789 |
I want member_group to then look like this
+-----------+----------+
| id_group |id_member |
+-----------+----------+
| 1 | 123 |
| 1 | 456 |
| 1 | 789 |
How can I do this (without resorting to shell scripts, for loops and sed) ?
As requested,
mysql> select * from group;
+----------+------------------+
| id_group | group_name |
+----------+------------------+
| 1 | vip-member |
| 2 | standard-member |
mysql> select * from member;
+-----------+----------+
| id_member | fullname |
+-----------+----------+
| 123 | Bob |
| 456 | Pete |
Which, if I could get it working, should look like below.
mysql> select * from member_group;
+------------------+----------+-----------+
| id_member_groups | id_group | id_member |
+------------------+----------+-----------+
| 1 | 1 | 123 |
| 2 | 1 | 456 |
| 3 | 1 | 789 |
| 4 | 2 | 123 |
| 5 | 2 | 789 |
id_group is supplied during the import phase. One batch of say 200 members, will be members of the same id_group. I was thinking about adding the group_id to a temporary table. But I'm a tad lost to be honest.
You can do a cross join to achieve your goal.
insert ignore into member_group (id_group, id_member)
select member_group.id_group, member.id_member
from member_group
cross join member
where group_name = 'MYGROUP';
I have table as below , I want to take latest rating for the client
basically user whenever updates rating, count will be incremented and a entry will be made in table. Table goes as below
-----------------------------------------------------
|_id| name | client_id | user_id | rating | count |
-----------------------------------------------------
|1 | Four | 1 | 1 | 4 | 1 |
|2 | three | 1 | 1 | 3 | 2 |
|3 | two | 1 | 1 | 2 | 3 |
|4 | five | 1 | 1 | 5 | 4 |
|5 | two | 1 | 2 | 2 | 1 |
|6 | three | 1 | 2 | 3 | 2 |
|7 | two | 2 | 1 | 2 | 1 |
|8 | three | 2 | 1 | 3 | 2 |
-----------------------------------------------------
For rating of client_id 1 I want out put like
-----------------------------------------------------
|_id| name | client_id | user_id | rating | count |
-----------------------------------------------------
|4 | five | 1 | 1 | 5 | 4 |
|6 | three | 1 | 2 | 3 | 2 |
-----------------------------------------------------
so far I tried SELECT * FROM test
where client_id = 1 group by client_id order by count desc;
but not getting expected result, any help??
You can use left join on the same table as
select t1.* from test t1
left join test t2 on t1.user_id = t2.user_id
and t1.client_id = t2.client_id
and t1._id < t2._id
where
t2._id is null
and t1.client_id = 1
order by t1.`count` desc;
Using un-correlated subquery you may do as
select t1.* from test t1
join (
select max(_id) as _id,
client_id,
user_id
from test
where client_id = 1
group by client_id,user_id
)t2
on t1._id = t2._id
and t1.client_id = t2.client_id
order by t1.`count` desc;
UPDATE : From the comment how to join another table into above , for this here is an example
mysql> select * from users ;
+------+------+
| _id | name |
+------+------+
| 1 | AAA |
| 2 | BBB |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from test ;
+------+-------+-----------+---------+--------+-------+
| _id | name | client_id | user_id | rating | count |
+------+-------+-----------+---------+--------+-------+
| 1 | four | 1 | 1 | 4 | 1 |
| 2 | three | 1 | 1 | 3 | 2 |
| 3 | two | 1 | 1 | 2 | 3 |
| 4 | five | 1 | 1 | 5 | 4 |
| 5 | two | 1 | 2 | 2 | 1 |
| 6 | three | 1 | 2 | 3 | 2 |
| 7 | two | 2 | 1 | 2 | 1 |
| 8 | three | 2 | 1 | 3 | 2 |
+------+-------+-----------+---------+--------+-------+
select t1.*,u.name from test t1
join users u on u._id = t1.user_id
left join test t2 on t1.user_id = t2.user_id
and t1.client_id = t2.client_id
and t1._id < t2._id
where
t2._id is null
and t1.client_id = 1
order by t1.`count` desc;
Will give you
+------+-------+-----------+---------+--------+-------+------+
| _id | name | client_id | user_id | rating | count | name |
+------+-------+-----------+---------+--------+-------+------+
| 4 | five | 1 | 1 | 5 | 4 | AAA |
| 6 | three | 1 | 2 | 3 | 2 | BBB |
+------+-------+-----------+---------+--------+-------+------+
Note that the join to users table is inner join and this will require all the user to be preset in users table which are in test table
If some users are missing in the users table then use left join this will have null values for the data selected from users table.
You may try something like
select _id, name, client_id, user_id, rating, max(count)
from clients
group by client_id
Try it
SELECT * FROM test
where client_id = 1
group by user_id
order by count desc
I have two tables like below,
mysql> select * from Books ;
+----+------+------------+----------+----------+
| id | name | author_name| category | category2|
+----+------+------------+----------+----------+
| 1 | 1 | Steve | CT001 | CT003 |
| 2 | 2 | John | CT002 | CT002 |
| 3 | 3 | Larry | CT003 | CT002 |
| 4 | 3 | Michael | CT004 | CT004 |
| 5 | NULL | Steven | CT005 | CT005 |
+----+------+------------+----------+----------+
mysql> select * from Codemst ;
+----+------+------------+
| id | code | name |
+----+------+------------+
| 1 | CT001| fiction |
| 2 | CT002| category1 |
| 3 | CT003| etc |
| 4 | CT004| etc2 |
| 5 | CT005| etc3 |
+----+------+------------+
I want to get human readable category name when I query like "select * from Books;"
If there was only one category in the Books table, I think I can use "Join" but, in this case what can I do?
select * from Books b
Inner Join Codemst c1 on b.category = c1.code
inner join codemst c2 on b.category2 = c2.code;
c1.name will hold the readable category, and c2.name the readable category2