SQL Select Data with condition on multiple rows - mysql

Suppose that I have a table called "tblTemp" with the following data
ID Name
1 A
2 B
3 C
4 A
4 B
5 A
5 B
5 C
6 C
6 B
I want to get ID from name of A&B only not A&B&C like below:
4 A
or
4 B
How can I do like this in sql?
I try the following sql but it return row 5 as well:
SELECT tblTemp.ID, tblTemp.Name
FROM tblTemp INNER JOIN
tblTemp AS tbltemp_1 ON tblTemp.ID = tbltemp_1.ID
WHERE (tblTemp.Name = 'A') AND (tbltemp_1.Name = 'B')

One of the ways to compare sets is to take the count of group, filter groups by search set, and see if number of matches per group equals original number of group members:
select tblTemp.ID
from tblTemp
inner join
(
select ID,
count(*) GroupCount
from tblTemp
group by ID
having count(*) = 2
) g
on tblTemp.ID = g.ID
where tblTemp.Name in ('A', 'B')
group by tblTemp.Id, g.GroupCount
having count (*) = g.GroupCount
This should work on both MySql and Sql Server.
You can play with this code # Sql Fiddle.

try:
SELECT distinct ID
FROM tblTemp a
LEFT JOIN tblTemp b
ON a.ID = b.ID AND
b.name = 'C'
WHERE b.ID IS NULL;

select id from table
group by id
having min(Name)='A' and max(Nmae)='B'

SELECT ID, Name FROM tblTemp WHERE (Name = 'A' OR Name = 'B') and ID not in(SELECT ID FROM tblTemp WHERE Name = 'C')

Do you just want a list of distinct IDs that have A or B but not C?
SELECT distinct ID
FROM tblTemp
WHERE Name = 'A' or Name = 'B'
EXCEPT
SELECT distinct ID
FROM tblTemp
WHERE Name = 'C'
My above solution work for 'A' and/or 'B', but I notice you actually want 'A' and 'B' with no or. In that case:
SELECT distinct ID
FROM tblTemp as T1
INNER JOIN tblTemp as T2
ON T1.ID = T2.ID
WHERE T1.Name = 'A' and T2.Name = 'B'
EXCEPT
SELECT distinct ID
FROM tblTemp
WHERE Name = 'C'
this is an extension of your original code and is perhaps not as elegant as #Madhivanan's solution but it is more general should A B and C change to words for example.

Related

Query table with composite primary key, excluding specific rows

product_id | category
---------------------
1 | A
1 | B
2 | A
3 | B
I would like to know which unique ids belong to category A but NOT category B.
In the example above, only id: 2 would be a valid result
I came up with this which does not work as intended:
SELECT id
FROM table
WHERE category = 'A' AND category <> 'B'
GROUP BY id
A valid approach would be to use a subquery
SELECT id
FROM table
WHERE category = 'A'
AND id NOT IN (SELECT id
FROM table
WHERE category = 'B')
Is it possible to do this with a single query?
Use a self-join:
SELECT t1.id
FROM table AS t1
LEFT JOIN table AS t2 ON t1.id = t2.id AND t2.category = 'B'
WHERE t1.category = 'A' and t2.id IS NULL
Another way is with grouping:
SELECT id
FROM table
WHERE category IN ('A', 'B')
GROUP BY id
HAVING MAX(category) = 'A'
Use aggregation and the conditions in the HAVING clause:
SELECT id
FROM tablename
GROUP BY id
HAVING SUM(category = 'A') > 0
AND SUM(category = 'B') = 0;
or:
SELECT id
FROM tablename
WHERE category IN ('A', 'B')
GROUP BY id
HAVING SUM(category = 'B') = 0;

MYSQL: Where all values in joined table are the same

Lets say we have two tables A and B.
Table A
id name
1 first row
2 second row
Table B
id table_a_id voided
1 1 true
2 1 true
3 2 false
4 2 true
So, I want to select all rows from table A, only if all entries from table B marked as voided.
I started with simple query
SELECT * FROM table_a a
INNER JOIN table_b b ON a.id = b.table_a_id
WHERE b.voided = true
and now I'm stuck, the query returns both rows which is logically correct, how to rewrite this query, please?
You could use:
SELECT a.id, a.name
FROM a
JOIN b
ON a.id = b.table_a_id
GROUP BY a.id, a.name
HAVING SUM(CASE WHEN voided THEN 0 ELSE 1 END) = 0;
DBFiddle Demo
Even simpler(without CASE):
SELECT a.id, a.name
FROM a
JOIN b
ON a.id = b.table_a_id
GROUP BY a.id, a.name
HAVING SUM(NOT voided) = 0;
-- HAVING NOT SUM(NOT voided);
You could use a NOT EXISTS clause:
SELECT *
FROM table_a as a
where not exists (select *
from table_b as b
where a.id=b.id and not b.voided);
select *
from table_a
where id not in (select table_a_id
from table_b
where voided = false );

GROUP BY and JOIN in HIVE

How can I do something like this in HIVE:
Table1:
ID Name Friends
1 Tom 5
Table2:
ID Name DOB
1 Jerry 10/10/1999
1 Kate Null
1 Peter 02/11/1983
1 Robert Null
1 Mitchell 09/09/2000
What I want to do is:
For each ID in table 1, find num of not null DOB and then divide by Friends
I wrote a query as:
SELECT t.ID, t.Friends, COUNT(s.DOB)/ t. Friends from Table1 t join Table2 s on (t.ID = s.ID) GROUP BY t.ID
When I do this, I get the error as FRIENDS is not part of the GROUP BY Key
The answer I am expecting is: 3/5
Just add the FRIENDS to your GROUP BY section:
SELECT t.ID, t.FRIENDS, COUNT(s.DOB)/ t. FRIENDS
from Table1 t
join Table2 s
on (t.ID = s.ID)
GROUP BY t.ID. t.FRIENDS
I prefer to write this kind of query like this:
SELECT t.ID, case when t.FIREND>0 then Cnt / t.FRIENDS ELSE 0 END
FROM Table t1
JOIN (Select ID, Count(*) AS Cnt from Table 1 GROUP BY Id) t2
ON t1.ID = t2.ID
if you have declare id,friends in table 1 as integer and id in table2 as integer, then below query will get you intended output
select a.name, concat(cast(b.cnt as string),'/',cast(a.friends as string))
from table1 a
join
(select id, count(DOB) as cnt from table2 where DOB is not null group by id) b
on (a.id = b.id)

Same id, different name, how to get name by another name?

This is my table:
id name
1 j
1 jack
1 john
So I have j and want find all names which id is equal to the id of j in single SQL?
select name
from your_table
where id in
(
select id from your_table where name = 'j'
)
Self join time
select t1.name
from your_table t1
inner join your_table t2 on t2.id = t1.id
where t2.name = 'j'

MySQL query count multiple values

Consider the following DB table:
c p
=========
1 'a'
1 'b'
2 'a'
2 'c'
Now, my goal is to retrieve a list of numbers c, for which holds that each number in this list has at least a record with p='a' AND p='b'.
In the example table above, that would be c=1.
Now my question is, how do I accomplish this using one MySQL query?
select t1.c
from MyTable t1
inner join MyTable t2 on t1.c = t2.c
where t1.p = 'a' and t2.p = 'b'
Update:
select c
from MyTable
where p in ('a', 'b', 'c', 'd')
group by c
having count(distinct p) = 4
There are different ways to attack the problem depending on the rules your data follows if any. Without knowing more about your problem, I would do:
SELECT t1.c FROM table t1 INNER JOIN table t2
ON t1.c = t2.c
WHERE t1.p = 'a' AND t2.p = 'b'