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

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

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

SQL: Searching for the correct record group

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.

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

Count value from database

I have below data.
ID UserID Grade
1 1 A
2 1 A
3 1 a
4 1 a
5 1 b
6 1 C
7 1 c
8 1 b
9 2 b
10 2 C
11 1 b
12 2 A
I want below results.
RunningNumber UserID Result Count
1 1 a 4
2 1 b 1
3 1 c 2
4 1 b 2
5 2 b 1
6 2 c 1
7 2 a 1
The result will count column Grade (case insensitive) and must be group by UserID.
Use as below
SELECT UserID, Grade, COUNT(ID) AS Count
FROM Table1
GROUP BY UserID,Grade;
Updated
SELECT ROW_NUMBER()
OVER (ORDER BY Grade) AS RunningNumber ,
UserID, Grade, COUNT(ID) AS Count
FROM Table1
GROUP BY UserID,Grade;
Just use Group by & count
SELECT ID ,UserID,Grade
COUNT(ID) FROM Tabel
GROUP BY Grade,UserID;
You can use DENSE_RANK for the RunningNumber, COUNT(*)OVER for the count per ID and ROW_NUMBER to take only the first row:
WITH CTE AS
(
SELECT
RunningNumber = DENSE_RANK() OVER (ORDER BY UserID, Grade),
UserID, Result = Grade,
[Count] = COUNT(*) OVER (PARTITION BY UserID, Grade),
RowNum = ROW_NUMBER() OVER (PARTITION BY UserID, Grade ORDER BY ID)
FROM dbo.TableName
)
SELECT RunningNumber, UserID, Result, [Count]
FROM CTE
WHERE RowNum = 1
Demo
$query_not="SELECT count(status) AS sum FROM `user_leave_details`WHERE (status='2' Or status='3') AND user_id_no='$user_id_no'";
$result=mysqli_query($bd,$query_not);
while($arr=mysqli_fetch_array($result))
{
$sum=$arr['sum'];
}
connect.php
<?php
$mysql_hostname = "localhost";
$mysql_user = "root";
$mysql_password = "";
$mysql_database = "";
$bd=mysqli_connect($mysql_hostname,$mysql_user,$mysql_password,$mysql_database);
?>

SQL: Get multiple line entries linked to one item?

I have a table:
ID | ITEMID | STATUS | TYPE
1 | 123 | 5 | 1
2 | 123 | 4 | 2
3 | 123 | 5 | 3
4 | 125 | 3 | 1
5 | 125 | 5 | 3
Any item can have 0 to many entries in this table. I need a query that will tell me if an ITEM has all it's entries in either a state of 5 or 4. For example, in the above example, I would like to end up with the result:
ITEMID | REQUIREMENTS_MET
123 | TRUE --> true because all statuses are either 5 or 4
125 | FALSE --> false because it has a status of 3 and a status of 5.
If the 3 was a 4 or 5, then this would be true
What would be even better is something like this:
ITEMID | MET_REQUIREMENTS | NOT_MET_REQUIREMENTS
123 | 3 | 0
125 | 1 | 1
Any idea how to write a query for that?
Fast, short, simple:
SELECT itemid
,count(status = 4 OR status = 5 OR NULL) AS met_requirements
,count(status < 4 OR status > 5 OR NULL) AS not_met_requirements
FROM tbl
GROUP BY itemid
ORDER BY itemid;
Assuming all columns to be integer NOT NULL.
Builds on basic boolean logic:
TRUE OR NULL yields TRUE
FALSE OR NULL yields NULL
And NULL is not counted by count().
->SQLfiddle demo.
SELECT a.ID FROM (SELECT ID, MIN(STATUS) AS MINSTATUS, MAX(STATUS) AS MAXSTATUS FROM TABLE_NAME AS a GROUP BY ID)
WHERE a.MINSTATUS >= 4 AND a.MAXSTATUS <= 5
One way of doing this would be
SELECT t1.itemid, NOT EXISTS(SELECT 1
FROM mytable t2
WHERE itemid=t1.itemid
AND status NOT IN (4, 5)) AS requirements_met
FROM mytable t1
GROUP BY t1.itemid
UPDATE: for your updated requirement, you can have something like:
SELECT itemid,
sum(CASE WHEN status IN (4, 5) THEN 1 ELSE 0 END) as met_requirements,
sum(CASE WHEN status IN (4, 5) THEN 0 ELSE 1 END) as not_met_requirements
FROM mytable
GROUP BY itemid
simple one:
select
"ITEMID",
case
when min("STATUS") in (4, 5) and max("STATUS") in (4, 5) then 'True'
else 'False'
end as requirements_met
from table1
group by "ITEMID"
better one:
select
"ITEMID",
sum(case when "STATUS" in (4, 5) then 1 else 0 end) as MET_REQUIREMENTS,
sum(case when "STATUS" in (4, 5) then 0 else 1 end) as NOT_MET_REQUIREMENTS
from table1
group by "ITEMID";
sql fiddle demo
WITH dom AS (
SELECT DISTINCT item_id FROM items
)
, yes AS ( SELECT item_id, COUNT(*) AS good_count FROM items WHERE status IN (4,5) GROUP BY item_id
)
, no AS ( SELECT item_id, COUNT(*) AS bad_count FROM items WHERE status NOT IN (4,5) GROUP BY item_id
)
SELECT d.item_id
, COALESCE(y.good_count,0) AS good_count
, COALESCE(n.bad_count,0) AS bad_count
FROM dom d
LEFT JOIN yes y ON y.item_id = d.item_id
LEFT JOIN no n ON n.item_id = d.item_id
;
Can be done with an outer join, too:
WITH yes AS ( SELECT item_id, COUNT(*) AS good_count FROM items WHERE status IN (4,5) GROUP BY item_id)
, no AS ( SELECT item_id, COUNT(*) AS bad_count FROM items WHERE status NOT IN (4,5) GROUP BY item_id)
SELECT COALESCE(y.item_id, n.item_id) AS item_id
, COALESCE(y.good_count,0) AS good_count
, COALESCE(n.bad_count,0) AS bad_count
FROM yes y
FULL JOIN no n ON n.item_id = y.item_id
;
Nevermind, it was actually easy to do:
select ITEM_ID ,
sum (case when STATUS >= 3 then 1 else 0 end ) as met_requirements,
sum (case when STATUS < 3 then 1 else 0 end ) as not_met_requirements
from TABLE as d
group by ITEM_ID