I want to check rows where uid equal both 1 and 2 and if they do, return cid. In this example there will only ever be 2, but if you know a way to return the CID for more than 2, that would be great too.
How can I most easily get the value where cid = 5 when I know both uid values? (1,2).
cid | uid |
------------
5 | 1 |
5 | 2 |
6 | 1 |
6 | 3 |
7 | 1 |
7 | 4 |
For pseudo sql, I am thinking something like SELECT cid WHERE uid = 1 or uid = 2
This returns all rows where uid has a 1 or a 2. How can I limit to an OR statement and an AND?
SELECT cid WHERE uid = 1 AND uid = 2 (but in multiple rows)
Any ideas?
As far as i understand you're looking for a way to apply a condition to multiple rows, a way to do that is through agrupation functions. try this:
Select CID
from YourTable where uid IN (1,2)
group by cid
having count(uid) = 2
in this example i'm using IN instead of two OR and i'm grouping the rows by CID, and after that i'm limiting the results to those rows that match with UID equals to 1 and 2.
There are many tricky ways of achieve the same result, for example you can also do something like:
Select CID
from YourTable where uid IN (1,2)
group by cid
having sum(uid) = 3
in this example i'm suming the UID column, if UID is 1 and 2 the sum of both will result on 3, I assume that you can't have 3 rows with the UID 1 and the same CID
According to given details, Try this. Let's say you have a table called docs;
SELECT d1.cid
FROM docs AS d1
LEFT JOIN docs AS d2 ON d1.cid = d2.cid
WHERE d1.uid = 1
AND d2.uid = 2
Related
I am not very good at sql but I am getting there. I have searched stackoverflow but I can't seem to find the solution and I hope someone out there can help me. I have a table (users) with data like the following. The book_id column is a key to another table that contains a book the user is subscribed to.
|--------|---------------------|------------------|
| id | book_id | name |
|--------|---------------------|------------------|
| 1 | 1 | jim |
| 2 | 1 | joyce |
| 3 | 1 | mike |
| 4 | 1 | eleven |
| 5 | 2 | max |
| 6 | 2 | dustin |
| 7 | 2 | lucas |
|--------|---------------------|------------------|
I have a function in my PHP code that returns two random users from a specific book id (either 1 or 2). Query one returns the result in column 1 and result two returns the results in column 2 like:
|---------------------|------------------|
| 1 | 2 |
|---------------------|------------------|
| jim | max |
| joyce | dustin |
|---------------------|------------------|
I have achieved this by running two separate queries as seen below. I want to know if it's possible to achieve this functionality with one query and how.
$random_users_with_book_id_1 = SELECT name FROM users WHERE book_id=1 LIMIT 2
$random_users_with_book_id_2 = SELECT name FROM users WHERE book_id=2 LIMIT 2
Again, I apologise if it's too specific. The query below has been closest to what I was trying to achieve.:
SELECT a.name AS book_id_1, b.name AS book_id_2
FROM users a, users b
WHERE a.book_id=1 AND b.book_id = 2
LIMIT 2
EDIT: I have created a fiddle to play around with his. I appreciate any help! Thank you!! http://sqlfiddle.com/#!9/7fcbca/1
It is easy actually :)
you can use UNION like this:
SELECT * FROM (
(SELECT * FROM user WHERE n_id=1 LIMIT 2)
UNION
(SELECT * FROM user WHERE n_id=2 LIMIT 2))
collection;
if you read this article about the documentation you can use the () to group the individual queries and the apply the union in the middle. Without the parenthesis it would still LIMIT 2 and show only the two first. Ref. "To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT:"
If you want to combine the queries in MySQL, you can just use parentheses:
(SELECT name
FROM users
WHERE n_id = 1
LIMIT 2
) UNION ALL
(SELECT name
FROM users
WHERE n_id = 2
LIMIT 2
);
First, only use UNION if you specifically want to incur the overhead of removing duplicates. Otherwise, use UNION ALL.
Second, this does not return random rows. This returns arbitrary rows. In many cases, this might be two rows near the beginning of the data. If you want random rows, then use ORDER BY rand():
(SELECT name
FROM users
WHERE n_id = 1
ORDER by rand()
LIMIT 2
) UNION ALL
(SELECT name
FROM users
WHERE n_id = 2
ORDER BY rand()
LIMIT 2
);
There are other methods that are more efficient, but this should be fine for up to a few thousand rows.
I have a table full of user answers to a question.
I want to be able to construct a SQL statement which returns their first answer (min), and their most recent answer (max), ending up with a result like this:
user_id | first_answer | last_answer
1 | 50 | 100
2 | 10 | 5
...the table looks like this:
answer_id | user_id | answer
1 | 1 | 50
2 | 2 | 10
3 | 1 | 100
4 | 2 | 5
Sorry I don't have any code to show, but I genuinely have zero idea how to achieve this, so any help would be greatly appreciated.
Edit:
By min and max, I mean the first answer, and the most recent answer for each user.
You can build a query for that in two steps. First you get first and last answers for each user
select user_id, min(answer_id) min_answer, max(answer_id) max_answer
from yourTable
group by user_id
Then you join that with the original table twice to get the corresponding values for both first and last answer
select t1.user_id, t2.answer as first_answer, t3.answer as last_answer
from (
select user_id, min(answer_id) min_answer, max(answer_id) max_answer
from yourTable
group by user_id
) t1
join yourTable t2
on t2.answer_id = t1.min_answer
join yourTable t3
on t3.answer_id = t1.max_answer
Suppose we have a table like the one below.
Id | Name | Group
-----------------
1 | John | 1
2 | Zayn | 2
3 | Four | 2
4 | Ben_ | 3
5 | Joe_ | 2
6 | Anna | 1
The query below will select all of them.
SELECT `Name` FROM `Table` WHERE 1;
How would I select only one person from each group? Who it is doesn't really matter, as long as there's only one name from group 1 and one name from group 2 etc.
The GROUP BY clause isn't fit for this (according to my error console) because I am selecting non aggregated values, which makes sense.
The DISTINCT clause isn't great here either, since I don't want to select the "Group" and definitely not group by their names.
If is not important the resulting name You can anawy leverage some group functions eg with max or min..
leverage the group functions
select max(name) from your_table
group by Group;
otherwise you can use subquery
select name from your_table
where Id in (select min(Id) from your_table group by Group);
given the following table (describing a many-to-many relation):
ID | PageID | TagID
--------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 2
4 | 2 | 3
how do i select 'all PageIDs having all of a list of TagIDs'?
in other words: i want all pages tagged with TagIDs 1 and 2 (so it's only PageID 1 in this example)
after some googling i found the term 'relational division' which might be relevant here, but i didn't quite get it. anyone having a simple query for my problem?
If you have the list of tagids in a table, then it is a simple join and group by:
select pageId
from t join
list l
on t.tagId = l.tagId cross join
(select count(*) cnt from list l) as const
group by pageId
having count(*) = max(cnt)
The having clause checks that all tags are present. If there might be duplicates, then you would want to replace the "count(*)" with "count(distinct tagid)" in both cases.
I have a table and data like this
id | term_id | name_id
1 | 4 | 1
2 | 6 | 1
3 | 5 | 2
4 | 6 | 2
3 | 4 | 3
4 | 6 | 3
I want a query so that I can get only those name_id which has 4 and 6 term_id attached to it ... if i query 4,6,2 it should not display me anything because no named_id is attached to all three of them or like 4,5 it should not display anything because non has same 4 and 5
SELECT Name_ID
FROM Table1 t
WHERE term_id IN (4,6)
GROUP BY NAME_ID
HAVING COUNT(*) = 2
This is it (if i understand what you want):
SELECT t1.name_id
FROM table1 t1
INNER JOIN table1 t2 ON t1.name_id=t2.name_id
WHERE (t1.term_id = 4 AND t2.term_id=6) OR (t1.term_id = 6 AND t2.term_id=4)
GROUP BY name_id;
When i run this query i get
+---------+
| name_id |
+---------+
| 1 |
| 3 |
+---------+
SELECT DISTINCT name_id
FROM t
WHERE
term_id = 4
AND
name_id IN (SELECT name_id FROM t WHERE term_id = 6)
select
name_id
from
YourTable
where
term_id = 4 or term_id = 6
group by
name_id
having
count(*) = 2
To clarify what is happening, you need to understand the "GROUP BY" and "HAVING" context. Group by forces the SQL query to group as many qualified records by the columns it is identifying as the "Group By" clause. This just happens to be the same single column in the query.
Next, the HAVING clause is based on the final results of the group after all records are pre-qualified and included. In this case, it is looking at the COUNT(*) of records that qualified = 2.
Since you were concerned with a given Name_ID being associated with BOTH Terms of 4 AND 6, we want any names where their ID was found in BOTH... Hence the OR condition of the WHERE clause. We want any record where a person was associated with 4 OR 6. If at the result, only ONE record was found (only a 4 or 6), their COUNT() value would be equal to 1 and thus discarded from the result set... Only those that qualify with BOTH terms would have a count() = 2 and thus included in the final results...
To see otherwise what it may look like, try this query...
select
name_id,
count(*) as TotalTermsPerName
from
YourTable
group by
name_id
You'll get all name ID with a minimum of 1 term, and others that could have 10 terms or more based on your data. Since the original query was only considering the terms of 4 AND 6, the maximum count that COULD be reached would be a max of 2.
Hope this helps, instead of just a query answer and not understanding the basis of HOW things work.