SQL: Searching for the correct record group - sql

Lets say that we have a Groupings table that has 2 columns: Group_ID and Item_ID. Both are ints. For a simplified example lets imagine that the Item_ID can be one of only 3 values: {1,2,3}. The Group_IDs then represent the different groups of permutations of this data. So for example:
Group_ID Item_ID
1 1
2 2
3 3
4 1
4 2
5 1
5 3
6 2
6 3
7 1
7 2
7 3
What SQL could I write that if I inputted a collection of Item_Ids it would return the Group_ID related to that collection?
So for example in the above with an input of (2,3) => 6
Edit: I want to use the solution query on a more complex table, where there are 16 different values for the Item_ID

use conditional aggregation
select group_id
from table t1
where Item_ID in(2,3)
and exists( select 1 from table t2 where t1.group_id=t2.group_id
having count(distinct t2.Item_ID)=2 )
group by group_id
having count(distinct item_id)=2

Another Sql to do this
SELECT Group_id
FROM YourTable
GROUP BY Group_id
HAVING COUNT(Item_ID) = 2
AND COUNT(CASE WHEN Item_ID = 2 THEN Item_ID END) > 0
AND COUNT(CASE WHEN Item_ID = 3 THEN Item_ID END) > 0

Assuming you have no duplicates, I would simply do:
select group_id
from t
group by group_id
having sum(case when Item_ID in (2, 3) then 1 else 0 end) = count(*) and
count(*) = 2;
This seems like the simplest approach.

Related

SQL to find IDs which never had a column value

Below is my data:
ID
request_type
1
3
1
2
1
1
1
4
1
5
2
3
2
2
3
4
3
2
I need a query to fetch IDs that never had a request type of 1 (e.g. 2,3 from the previous table).
With conditional aggregation:
select id
from tablename
group by id
having count(case when request_type = 1 then 1 end) = 0
SELECT DISTINCT `ID`
FROM `my_table`
WHERE `ID` NOT IN (
SELECT DISTINCT `ID`
FROM `my_table`
WHERE `request_type` = 1
)
If 1 is the lowest possible value:
select ID
from tab
group by ID
having min (request_type) > 1
Or more generic:
select ID
from tab
group by ID
having max(case when request_type = 1 then 1 else 0 end) = 0

Find Common Rows for some Row Values in SQL

I have a table with Ids and a subId column. And I have a user defined data type with a list of SubIds. I want all those ids which have all the sub-ids present in my user-defined data type. for example:
The table is:
ID SubID
1 2
1 3
1 4
2 3
2 4
2 2
3 3
3 2
and the data type is
CREATE TYPE SubIds AS TABLE
( SubId INT );
GO
With Value
SubID
3
4
I want the output to be
ID
1
2
Because only the ID 1 and 2 contain both the subIds 3 & 4
Note: the combination of Id and Sub ID will always be unique if its of any use
Let's assume that #s is your table of ids:
select t.ID
from t
Where t.SubId in (select SubId from #s)
group by t.Id
having count(*) = (select count(*) from #s);
This assumes that the two tables do not have duplicates. If duplicates are present, you can use:
select t.ID
from t
Where t.SubId in (select SubId from #s)
group by t.Id
having count(distinct t.SubId) = (select count(distinct s.SubId) from #s s);
Try this way
select ID
from yourtable
Where SubID in (3,4)
Group by ID
having Count(distinct SubID)=2
Another more flexible approach
select ID
from yourtable
Group by ID
having sum(case when SubID = 3 then 1 else 0 end) >= 1
and sum(case when SubID = 4 then 1 else 0 end) >= 1
If you want to pull SubId's from SubIds table type then,
SELECT ID
FROM yourtable T
JOIN (SELECT SubID,
Count(1) OVER() AS cnt
FROM SubIds) S
ON T.SubID = S.SubID
GROUP BY ID,Cnt
HAVING Count(DISTINCT T.SubID) = s.cnt

Exclude value of a record in a group if another is present

In the example table below, I'm trying to figure out a way to sum amount over id for all marks where mark 'C' doesn't exist within an id. When mark 'C' does exist in an id, I want the sum of amounts over that id, excluding the amount against mark 'A'. As illustration, my desired output is at the bottom. I've considered using partitions and the EXISTS command, but I'm having trouble conceptualizing the solution. If any of you could take a look and point me in the right direction, it would be greatly appreciated :)
sample table:
id mark amount
------------------
1 A 1
2 A 3
2 B 2
3 A 2
4 A 1
4 B 3
5 A 1
5 C 3
6 A 2
6 C 2
desired output:
id sum(amount)
-----------------
1 1
2 5
3 2
4 4
5 3
6 2
select
id,
case
when count(case mark when 'C' then 1 else null end) = 0
then
sum(amount)
else
sum(case when mark <> 'A' then amount else 0 end)
end
from sampletable
group by id
Here is my effort:
select id, sum(amount) from table t where not t.id = 'A' group by id
having id in (select id from table t where mark = 'C')
union
select id, sum(amount) from table t where t.id group by id
having id not in (select id from table t where mark = 'C')
SELECT
id,
sum(amount) AS sum_amount
FROM atable t
WHERE mark <> 'A'
OR NOT EXISTS (
SELECT *
FROM atable
WHERE id = t.id
AND mark = 'C'
)
GROUP BY
id
;

How to GROUP BY in SQL and then mark as 0,1

I need to GROUP BY item_id and check if user_id in any of those matches a variable. If so, I want it to = 1, if not 0.
for example, imagine table like this:
item_id, user_id
1 1
1 3
2 4
2 1
2 7
2 3
3 4
3 6
4 8
4 1
5 3
IF (user_id = 3,1,0) AS match,
Want my Query to come back as
item_id, match
1 1
2 1
3 0
4 0
5 1
Where "1" all occurrences of user_id 3 in an item_id group.
You need the right aggregation function:
select item_id,
max(case when user_id = 3 then 1 else 0 end) as hasmatch
from t
group by item_id
order by item_id
In MySQL, true is 1 and false is 0, so you can just do:
SELECT item_id, MAX(user_id = 3) AS has_match
FROM table
GROUP BY 1
You can even count the number of matches:
SELECT item_id, SUM(user_id = 3) AS matches
FROM table
GROUP BY 1
GROUP BY 1 is short for GROUP BY item_id, as item_id is the first select expression.
I would do it as follows:
SELECT
A.item_id, ISNULL(B.count, 0)
FROM
(SELECT DISTINCT item_id 'item_id' FROM myTable) AS A
LEFT JOIN
(
SELECT item_id, count(*) 'count'
FROM myTable WHERE user_id IN (3, 1, 0)
GROUP BY item_id
) AS B
ON A.item_id = B.item_id

use count in sql

I need a SQL statement, the requirement is: there is a table, which has two columns: ID, Owner_ID; I inserted several records, for example:
ID Owner_ID
0 0
1 0
2 1
3 1
4 2
5 3
6 3
7 3
8 3
9 0
Now I need a SQL statement, which returns a ID list sorted by the number of rows owned by different user, from largest to smallest. In this example, owner 3 has four rows; owner 0 has three rows, owner 1 has two rows; and owner 2 has one rows. the result should be
ID Owner_ID
5 3
6 3
7 3
8 3
0 0
1 0
9 0
2 1
3 1
4 2
I think I should use the aggregate function count, does anybody have an idea?
I am using HSQLDB.
Thanks in advance!!
This will work with most SQL DBMS, but shows the count value.
SELECT ID, Owner_ID, Owner_Count
FROM AnonymousTable AS A
JOIN (SELECT Owner_ID, COUNT(*) AS Owner_Count
FROM AnonymousTable
GROUP BY Owner_ID
) AS B ON B.Owner_ID = A.Owner_ID
ORDER BY Owner_Count DESC, Owner_ID ASC, ID ASC;
This will work with some, but not necessarily all, DBMS; it orders by a column that is not shown in the result list:
SELECT ID, Owner_ID
FROM AnonymousTable AS A
JOIN (SELECT Owner_ID, COUNT(*) AS Owner_Count
FROM AnonymousTable
GROUP BY Owner_ID
) AS B ON B.Owner_ID = A.Owner_ID
ORDER BY Owner_Count DESC, Owner_ID ASC, ID ASC;
This is very straight-forward.
SELECT
ID,
Owner_ID
FROM
TheTable t
ORDER BY
(SELECT COUNT(*) FROM TheTable i WHERE i.Owner_ID = t.Owner_ID) DESC
Yes, you have the general idea. Try the following query:
select t.ID, t.Owner_ID
from table t
inner join (select Owner_ID, count(*) c from table t group by Owner_ID) tc
on t.Owner_ID = tc.Owner_ID
order by
tc.c desc, t.ID asc