Select where count of other query of same table - sql

I have got table "Members" with fields ID,UserID,GroupID
And I would like to select only GroupIDs where count of Members is more than 1 for each members, like this:
ID UserID GroupID
1 1 1 /* we are selecting groups for guy with ID 1, here are 3 people */
2 2 1
3 3 1
4 1 2 /* here the guy is alone in group, ignore him! */
5 1 3 /* select this one too for guy 1, because #members>1 */
6 2 3
Performing group select for guy with ID 1 including that there must be atleast 2 people in same group, so this would return: 1, 3
But I have no idea how to do this in SQL, I would like to do something like this, but, it obviously doesn't work:
SELECT GroupID
FROM Members
WHERE UserID=1
AND COUNT(
SELECT UserID FROM Members WHERE GroupID=**currently iterated group**
)>1;
Is it somehow possible?

If I understand correctly, you want groups with at least two members, one of which has userid = 1. The following query finds these groups using group by and having:
select m.groupId
from Members m
group by m.groupId
having count(*) > 1 and
sum(case when m.userid = 1 then 1 else 0 end) > 0;

This will return the groups with more than one member that user 1 is a member of:
select groupid
from members
where groupid in (select groupid from members where userid = 1)
group by groupid having count(*) > 1;
The solution offered by #GordonLinoff is probably better (more efficient) though.

Related

SQL Server -- Join Issue

I have a table with following rows :
SectionId
SectionStatus
1
Assigned
1
Approved
2
Assigned
2
Assigned
3
Assigned
Now I want to fetch the SectionId where al SectionStatus belong to that SectionId are not Approved.
Result expected for above table : 1,2,3
Another Example :
SectionId
SectionStatus
1
Approved
1
Approved
2
Assigned
2
Assigned
3
Assigned
Result expected for above table : 2,3
This looks like aggregation with a conditional count in the HAVING clause.
SELECT t.SectionId
FROM yourtable t
GROUP BY t.SectionId
HAVING COUNT(CASE WHEN t.SectionStatus = 'Approved' THEN 1 END) = 0;
db<>fiddle
One way to get that is by cross-applying the record and check whether that is 'Approved' or not.
Try the following:
select distinct SectionId from yourtable tab
cross apply (select 'Approved' Stat)t
where t.Stat <> tab.SectionStatus
Please see the db<>fiddle here.

Count combined with select distinct

actually i try to find a way to select all distinct private message from a table and also got the count of each in 1 sql query
the actual table have column with the id of the member and also a column
with the actual view state of the message when the message state = 0 it mean
not read
example of data in table
roger 0
paul 1
roger 0
paul 0
mike 0
mike 0
mike 0
then the result i want is
roger 2
paul 1
mike 3
any help will be apreciated thanks
Are you looking for this?
SELECT member_id, COUNT(*) AS count
FROM messages
WHERE state = 0
GROUP BY member_id
Here is a dbfiddle demo
I need also to select all field from another table that will match the member_id is that possible in 1 query
Sure, JOIN away
SELECT m.*, t.*
FROM (
SELECT member_id, COUNT(*) AS count
FROM messages
WHERE state = 0
GROUP BY member_id
) m JOIN other_table t
ON m.member_id = t.member_id

How to select id's that have rows for all values from a set

I want to select all Id from a table that have rows for both programs 'basketball' and 'football'
Given a table like this:
Id program
1 basketball
2 football
3 basketball
2 basketball
1 football
4 football
5 basketball
How can I get a result like this:
id
1
2
Since you want to return the id's that have both values football and basketball, you can use the following to get the result:
select id
from yt
where program in ('basketball', 'football')
group by id
having count(distinct program) = 2;
See SQL Fiddle with Demo.
Since can also be done by joining on your table multiple times:
select t1.id
from yt t1
inner join yt t2
on t1.id = t2.id
where t1.program = 'basketball'
and t2.program = 'football';
See SQL Fiddle with Demo
I think aggregation is the most generalizable approach for this:
select id
from table
group by id
having sum(case when program = 'Football' then 1 else 0 end) > 0 and
sum(case when program = 'Basketball' then 1 else 0 end) > 0
The sum() statement are counting the number of rows that have "football" and "basketball" respectively. When present, the number is greater than 0.
You can do this with IN or OR syntax:
SELECT id
FROM table
WHERE program = 'basketball'
OR program = 'football';
If you want to only get the first two results, add LIMIT 2 to the end.
By the way, it's really bad practice to have a table without a primary key, there is no way to index this table so performance would be very bad.

SQL - Removing Duplicate without 'hard' coding?

Heres my scenario.
I have a table with 3 rows I want to return within a stored procedure, rows are email, name and id. id must = 3 or 4 and email must only be per user as some have multiple entries.
I have a Select statement as follows
SELECT
DISTINCT email,
name,
id
from table
where
id = 3
or id = 4
Ok fairly simple but there are some users whose have entries that are both 3 and 4 so they appear twice, if they appear twice I want only those with ids of 4 remaining. I'll give another example below as its hard to explain.
Table -
Email Name Id
jimmy#domain.com jimmy 4
brian#domain.com brian 4
kevin#domain.com kevin 3
jimmy#domain.com jimmy 3
So in the above scenario I would want to ignore the jimmy with the id of 3, any way of doing this without hard coding?
Thanks
SELECT
email,
name,
max(id)
from table
where
id in( 3, 4 )
group by email, name
Is this what you want to achieve?
SELECT Email, Name, MAX(Id) FROM Table WHERE Id IN (3, 4) GROUP BY Email;
Sometimes using Having Count(*) > 1 may be useful to find duplicated records.
select * from table group by Email having count(*) > 1
or
select * from table group by Email having count(*) > 1 and id > 3.
The solution provided before with the select MAX(ID) from table sounds good for this case.
This maybe an alternative solution.
What RDMS are you using? This will return only one "Jimmy", using RANK():
SELECT A.email, A.name,A.id
FROM SO_Table A
INNER JOIN(
SELECT
email, name,id,RANK() OVER (Partition BY name ORDER BY ID DESC) AS COUNTER
FROM SO_Table B
) X ON X.ID = A.ID AND X.NAME = A.NAME
WHERE X.COUNTER = 1
Returns:
email name id
------------------------------
jimmy#domain.com jimmy 4
brian#domain.com brian 4
kevin#domain.com kevin 3

mysql SELECT COUNT(*) ... GROUP BY ... not returning rows where the count is zero

SELECT student_id, section, count( * ) as total
FROM raw_data r
WHERE response = 1
GROUP BY student_id, section
There are 4 sections on the test, each with a different number of questions. I want to know, for each student, and each section, how many questions they answered correctly (response=1).
However, with this query, if a student gets no questions right in a given section, that row will be completely missing from my result set. How can I make sure that for every student, 4 rows are ALWAYS returned, even if the "total" for a row is 0?
Here's what my result set looks like:
student_id section total
1 DAP--29 3
1 MEA--16 2
1 NNR--13 1 --> missing the 4th section for student #1
2 DAP--29 1
2 MEA--16 4
2 NNR--13 2 --> missing the 4th section for student #2
3 DAP--29 2
3 MEA--16 3
3 NNR--13 3 --> missing the 4th section for student #3
4 DAP--29 5
4 DAP--30 1
4 MEA--16 1
4 NNR--13 2 --> here, all 4 sections show up because student 4 got at least one question right in each section
Thanks for any insight!
UPDATE: I tried
SELECT student_id, section, if(count( * ) is null, 0, count( * )) as total
and that didn't change the results at all. Other ideas?
UPDATE 2: I got it working thanks to the response below:
SELECT student_id, section, SUM(CASE WHEN response = '1' THEN 1 ELSE 0 END ) AS total
FROM raw_data r
WHERE response = 1
GROUP BY student_id, section
SELECT student_id, section, sum(case when response=1 then 1 else 0 end) as total
FROM raw_data_r GROUP BY student_id, section
Note that there's no WHERE condition.
SELECT r.student_id,
r.subject,
sum( r.response ) as total
FROM raw_data r
GROUP BY student_id, subject
if you have a separate table with student information, you can select students from that table and left join the results to the data_raw table:
SELECT si.student_name, rd.student_id, rd.section, rd.count(*) AS total
FROM student_info AS si LEFT JOIN raw_data AS rd USING rd.student_id = si.student_id
This way, it first selects all students, then executes the count command.