Condense 3 SELECTS down to one table - mysql

The three statement (a little contrived for simplicity) are:
SELECT `user_id` WHERE `movie_id` = 1
SELECT `user_id` WHERE `movie_id` = 2
SELECT `user_id` WHERE `movie_id` = 3
What I would like to do is twofold:
Join the three of the above into a single table of ID's that match all three of the movie_id
Make all of this one query to reduce MySQL reads to speed up performance
I am sure there is a simple way to do it, but I am not the strongest SQL user, so thanks for all of the help!

Select count(distinct movie_ID), user_ID
from table where move_Id in (1,2,3)
group by user_ID
Having count(distinct Movie_ID) = 3
What this does is obtain a distinct count of movies per user_ID. it then limits the results to only those users having a count of 3.

The simplest way to me seems:
SELECT user_id FROM table_name WHERE movie_id IN (1,2,3);
Alternatively you could use the UNION method suggested by xQbert, but I would run an EXPLAIN query to see what SQL statement provided the most efficient result.

Related

Compare multiple values to subquery result in where clause

I have two related tables as follows :
USERS
user_id <\PK>
USERACTIONS
user_action_id <\PK>
user_id <\FK>
user_action <\int>
Whenever user performs an action, there is a new insertion in "useractions" table. I need a query to fetch those USERACTION rows where user performed only particular set of actions say (1,2) but not (3,4).
So I have a query like -
select * from USERACTIONS where (1,2) in(select user_action from USERACTIONS where user_id=100) and user_id=100;
Problem is the above query doesn't work as supplying (1,2) expects subquery also to return two columns which is understandable. This is the error I get -
ERROR: subquery has too few columns
Giving a single value say (1) or (2) works perfectly. I want to know if there is any way I can use the same query and compare the subquery's result with multiple values? I prefer the same query because the case demonstrated here is just a part of a large query.
Please note the query should not list users who performed (1,2,3,4) those who performed only (1,2) should be listed and also user_action values can be any random integer.
Any alternate queries are welcome but would prefer changes in the same query. Thanks in advance.
try this:
SELECT USERS.user_id, USERACTIONS.user_action
FROM USERACTIONS
LEFT JOIN USERS ON USERS.user_id = USERACTIONS.user_id where USERACTIONS.user_action in (1,2);
This Works for your query.
You add the numbers to the in Clause
SELECT a.user_id
FROM
(SELECT DISTINCT user_id
from
USERACTIONS
WHERE user_action
IN (1,2)) a
INNER JOIN
(SELECT DISTINCT user_id
from
USERACTIONS
WHERE user_action
NOT IN (1,2)) b
ON a.user_id <> b.user_id
;
CREATE TABLE USERACTIONS (id INT NOT NULL AUTO_INCREMENT
, PRIMARY KEY(id)
, user_action INT
, user_id INT
);
INSERT USERACTIONS VALUES (NULL,1,100),(NULL,2,100),(NULL,3,100), (NULL,1,101),(NULL,2,101);
✓
✓
SELECT a.user_id
FROM
(SELECT DISTINCT user_id
from
USERACTIONS
WHERE user_action
IN (1,2)) a
INNER JOIN
(SELECT DISTINCT user_id
from
USERACTIONS
WHERE user_action
NOT IN (1,2)) b
ON a.user_id <> b.user_id
;
| user_id |
| ------: |
| 101 |
db<>fiddle here
I see typical SO answers that aren't answering OP's question, but rather trying to steer them in a different direction. I know this is old, but if anyone stumbles upon this, I believe this will be more helpful.
I too have a large, enterprise solution where the WHERE check is MUCH more performant in a subquery than using a JOIN.
You can set a variable in your WHERE clause and use it afterwards. I am currently trying to find a better way to do this without setting a variable, but something like this works:
SELECT * FROM USERACTIONS
WHERE
( #useraction =
(select user_action from USERACTIONS where user_id=100 LIMIT 1)
= 1
OR #useraction = 2)
AND user_id=100;
What you are doing is creating a variable in your WHERE clause, setting that variable, then using it later. This is encapsulated, so it can match either one of the conditions.

voting system, relational db, sql query

I want to design voting system with two tables.
First table contains candidates' index and name.
The other one contains index, voter and candidate's index whom the voter support.
One voter can support multiple candidates.
I want a sql query that shows candidates' name with number of its supporters.
So the result looks like
John 12, Bob 8, David 3...
SELECT `name`, COUNT(table2.voter) AS `count`
FROM `table1`
LEFT JOIN `table2`
ON table1.idx = table2.support
ORDER BY COUNT(table2.voter) DESC;
The above query gave only one row with total number of voter.
Can anyone give me any hints?
SELECT `name`, COUNT(table2.voter) AS `count`
FROM `table1`
LEFT JOIN `table2` ON table1.idx = table2.support
GROUP BY `name`
ORDER BY COUNT(table2.voter) DESC;
You were missing a group by and hence getting only the first result.
You need to GROUP BY the non-aggregate column (name), otherwise the query will default to one group; the entire result set; and pick an arbitrary name:
SELECT `name`, COUNT(table2.voter) AS `count`
FROM `table1`
LEFT JOIN `table2`
ON table1.idx = table2.support
GROUP BY `name`
ORDER BY count DESC;
You can use column aliases in an ORDER BY, so I have update this also

MySQL view count and sum and other operations from multiple tables

Here is my situation:
I have 4 tables that all contains a column called score in all of these tables my goal for a view to create operations to the result of the 4 tables getting the following values:
Total score
Total number of rows
average (total score / number of rows)
Now i know that i would be able to create the view as:
(SELECT * FROM table1 where condition) + (SELECT * FROM table2 where condition)
So on and so forth.
but for each of the three goals i have i would have to nested select all tables atleast 2 times.
So my question is how do you handle a case like this? is there any operation in sql that makes this an easy task or am i bound to do something redundant?
Update
So my full case is that every use in my system has something called a division_id now i want to use this ID to find out what the score is for each division:
(PLEASE IGNORE THE _COPY)
You could use a UNION to join the 4 tables, since there is no join condition. There are a couple of ways that you could do this with the division field. Probably the most concise is:
select division_id, count(*), avg(scores.score), sum(scores.score) from
user join
(select id as user_id, score from user
UNION ALL
select user_id, score from test_score
UNION ALL
select user_id, score from task_score
UNION ALL
select user_id, score from offline_score) as scores
on user.id = scores.user_id
group by division_id
Link to SQLFiddle

Get biggest COUNT(DISTINCT) with condition mysql

right now I'm trying to return the biggest COUNT(DISTINCT column)-number from a mysql table.
It's hard to describe, so I'll give you an example:
My table has the following columns: s_id, k_id, p_id.
Now I want to count the different s with the condition that every entry has the same p_id, too. I need this to prepare a HTML-Table (so i know how many Columns this table will have).
Data Example:
This is what I got, so far:
SELECT COUNT(DISTINCT k_id) AS a FROM `table`
the problem with this is, that there may be 4 different k_ids but 3 of them are related to p_id = 1 and the last one is releated to p_id = 2.
a returns 4 instead of 3.
Thanks for support!
I think you want this:
select p_id, count(distinct s_id) as cnt
from table
group by p_id
order by cnt desc
limit 1;
Please consider this:
select max(count(distinct(k_id))) from table
group by p_id

MySQL filters query

I got table of links between goods and filters, like this:
id, good_id, filter_id.
When user notes checkboxes i have to show him all goods, that got link with all of those filters.
My vision of the query is:
(if user checked filters: 1,2 and 3)
SELECT DISTINCT(t0.gid)
FROM links as t0, links as t1, links as t2
WHERE t0.filter_id=1 AND
t1.good_id=t0.good_id AND t1.filter_id=2 AND
t2.good_id=t1.good_id AND t2.filter_id=3
But in this way, we'll got a trouble, if there are a lot of checked filters..
So, how would you solve the task?
If you need GID's which have at least one of filters
SELECT DISTINCT `gid` FROM `links` WHERE `filter_id` IN (1,2,3)
If you need GID's which have ALL filters 1,2,3
SELECT `gid` FROM `links` WHERE `filter_id` IN (1,2,3)
GROUP BY `gid` HAVING COUNT( DISTINCT `filter_id`)=3
where COUNT( DISTINCTfilter_id)=3 means that all 3 filters are on.
SELECT gid
FROM links
WHERE filter_id IN (1, 2, 3)
GROUP BY
gid
HAVING COUNT(DISTINCT filter_id) = 3