SQL count of return users - mysql

I'm trying to return a count of return users which happens when there is a duplicate 'user_id and action_type'.
So if you refer below, I would like my output to be = 2, since user_id (5) has 2 similar action_types (234) and user_id (6) also has 2 similar action_types (585).
How do I structure my query to reflect this?
Table t1
User_Id Action_Type
--------- ------------
5 234
5 846
5 234
6 585
6 585
7 465

SELECT COUNT(DISTINCT User_Id) FROM (
SELECT User_Id
FROM t1
GROUP BY User_Id, Action_Type
HAVING COUNT(*) > 1
) t

SELECT COUNT(User_ID) DuplicateRecordsUsers
FROM
(SELECT User_ID, Action_Type, COUNT(User_ID) Records
FROM Table
GROUP BY User_ID, Action_Type
HAVING COUNT(User_ID) > 1
)

SELECT COUNT(User_Id) FROM (
SELECT User_Id
FROM t1
GROUP BY User_Id, Action_Type
HAVING COUNT(*) > 1
) t
DISTINCT not required just count the ids returned

Related

Compare query result are equal

package_id
item_id
1
1
1
2
2
1
3
1
3
2
How can I check in one query does
SELECT item_id
FROM table
where package_id =1`
is equal to
SELECT item_id
FROM table
where package_id =3
EXECPT or WHERE NOT IN
won't work if e.g.
SELECT EXISTS(
SELECT item_id
FROM table
where package_id=2
and item_id NOT IN (
SELECT item_id
FROM table
where package_id =3
)
)
I don't know what do you want to do with this query, but I think you need to review your approach.
Anyway, this query allows you to check if the result of query1 and the query 2 has the same
SELECT true AS isSame
FROM (SELECT item_id,
Sum(q1) AS q1Sum,
Sum(q2) AS q2Sum
FROM ((SELECT DISTINCT item_id,
1 AS q1,
0 AS q2
FROM packages
WHERE package_id = 1)
UNION ALL
(SELECT item_id,
0 AS q1,
1 AS q2
FROM packages
WHERE package_id = 2)) allItems) allItemsWithSum
WHERE q1sum = q2sum

Group by select based on OR condition

After using UNION with two select queries, I'm getting following results
UserId Name Status
------ ------ --------
1 User1 Active
2 User2 Active
1 User1 InActive
3 User3 InActive
But the expected results is
UserId Name Status
---------------------
1 User1 Active
2 User2 Active
3 User3 InActive
Here what I need is, I want to group by column Id and get status as Active if any one result is active. How to form a SQL query for this?
Can anyone suggest query for any one of the following DB?
MSSQL
Oracle
MySQL
PostgreSQL
Edit:
This is the query I've tried in PostgreSQL
(SELECT DISTINCT User.Id,User.DisplayName,AppAccessToUsers.IsActive='1' AND User.IsActive='1' AS IsStatusActive
FROM Applications Left JOIN AppAccessToUsers ON (Applications.Id=AppAccessToUsers.ApplicationId)
Left JOIN User ON (AppAccessToUsers.UserId=User.Id) WHERE Applications.ClientId='e7e66c1b-b3b8-4ffb-844b-fc4840803265')
UNION
(SELECT DISTINCT User.Id,User.DisplayName,AppAccessToGroups.IsActive='1' AND Group.IsActive='1' AND UserGroup.IsActive='1' AND User.IsActive='1' AS IsStatusActive
FROM Applications Left JOIN AppAccessToGroups ON (Applications.Id=AppAccessToGroups.ApplicationId)
Left JOIN Group ON (AppAccessToGroups.GroupId=Group.Id) Left JOIN UserGroup ON (Group.Id=UserGroup.GroupId)
Left JOIN User ON (UserGroup.UserId=User.Id) WHERE Applications.ClientId='e7e66c1b-b3b8-4ffb-844b-fc4840803265')
Use this query,
SELECT UserId
,Name
,CASE WHEN min(status) = 'Active' THEN 'Active' ELSE 'InActive' END
FROM users GROUP BY UserId,Name
I would do the following, assuming a) your tables are called t1 and t2 (amend as appropriate for your actual table names) and b) the names for each userid in both tables are the same - ie. for userid = 1, both tables have the same name:
SELECT userid,
NAME,
MIN(status)
FROM (SELECT userid, NAME, status FROM t1
UNION ALL
SELECT userid, NAME, status FROM t2)
GROUP BY userid, NAME;
This works in Oracle, and I'm pretty sure it'll work in the other database platforms you mentioned.
N.B. I used MIN(status) since you appear to want a status of Active to override a status of Inactive, and A comes before I in the alphabet.
In Sql-server, you could use group by or Row_number like this
DECLARE #SampleData AS TABLE
(
UserId int,
Name varchar(20),
Status varchar(10)
)
INSERT INTO #SampleData
(
UserId,Name,Status
)
VALUES
(1,'User1', 'Active'),
(2,'User2', 'Active'),
(1,'User1', 'InActive'),
(3,'User3', 'InActive')
-- use row_number
;WITH temp AS
(
SELECT *, row_number() OVER(PARTITION BY sd.UserId ORDER BY sd.Status ) AS Rn
FROM #SampleData sd
)
SELECT t.UserId, t.Name, t.Status
FROM temp t WHERE t.Rn = 1
--or use group by
SELECT sd.UserId, sd.Name, min(sd.Status) AS status
FROM #SampleData sd
GROUP BY sd.UserId, sd.Name
Results:
UserId Name Status
1 User1 Active
2 User2 Active
3 User3 InActive
In case of MS Sql Server you can try row_number
;with cte as (
select top 1 with ties * from
( select * from #youruser
union all
select * from #youruser) a
order by row_number() over (partition by userid order by [status] desc)
) select * from cte where status = 'Active'
select your_table.* from your_table
inner join (
select UserId, min(Status) as st from your_table
group by UserId
) t
on your_table.UserId = t.UserId and your_table.Status = t.st
Note: if same UserId can have same Status more than 1 times, then this returns duplicated results.
;With cte (UserId, Name,Status)
AS
(
SELECT 1,'User1','Active' Union all
SELECT 2,'User2','Active' Union all
SELECT 1,'User1','InActive' Union all
SELECT 3,'User3','InActive'
)
SELECT UserId
,NAME
,[Status]
FROM (
SELECT *
,ROW_NUMBER() OVER (
PARTITION BY UserId
,NAME ORDER BY STATUS
) AS Seq
FROM cte
) dt
WHERE dt.Seq = 1
OutPut
UserId Name Status
-----------------------
1 User1 Active
2 User2 Active
3 User3 InActive
for postgres you can use CASE and bool_or, eg:
t=# with a(i,n,b) as (
values (1,'a','active'), (1,'a','inactive'), (2,'b','inactive'), (2,'b','inactive')
)
select i,n,case when bool_or(b = 'active') then 'active' else 'inactive' end
from a
group by i,n
;
i | n | case
---+---+----------
1 | a | active
2 | b | inactive
(2 rows)
Another approach:
Note : Group by is to remove duplicate
select
A.USERID, A.NAME,A.STATUS
from TAB_1 A
LEFT JOIN
(SELECT * FROM TAB_1 WHERE STATUS='Active') B
ON A.USERID=B.USERID
WHERE
( B.STATUS IS NULL OR A.STATUS=B.STATUS)
GROUP BY A.USERID, A.NAME,A.STATUS
ORDER BY A.USERID
;

SQL count without group by

I have a table that has user_id and purchase_id. I want to filter the table so that only users with more than 2 purchases (i.e. there are more than 2 rows for that user in the table). I used count and group by, but it does not work in a way I want.
create view myview as
select user_Id, purchase_id, count(*) as count from mytable group by user_Id;
select user_id, purchase_id from myview where count >2;
But it gives me only users (only one user_id) that has more than 2 purchase and it does not give me all of their purchases. For example if the table looks like this:
user_id purchase_id
1 1212
1 1312
2 1232
1 1321
3 1545
3 4234
My query gives me this :
1 1212
3 1545
But I want this:
1 1212
1 1312
1 1321
3 1545
3 4234
change your last sql like this
select mt.user_id, mt.purchase_id
from myview mv
inner join mytable mt
on mt.user_id=mv.user_id where mv.count >5;
SELECT
*
FROM
mytable mt,
(SELECT user_id, count(*) AS purchase_count FROM mytable GROUP BY user_id) ct
WHERE
mt.user_id = ct.user_id AND ct.purchase_count > 5;
SELECT *
FROM MYTABLE
WHERE USER_ID IN (SELECT USER_ID
FROM MYTABLE
GROUP BY USER_ID
HAVING COUNT(*)>=2)
I tested in my netezza,it works. hopefully, it's also working in mysql
Try GROUP BY with HAVING comment.
SELECT user_Id, purchase_id
FROM mytable
GROUP BY user_Id
HAVING count( * ) >5
As far as I can tell you want to list the user id's and purchase id's of all users that have over 5 purchases.
In order to do this you could do a join on two queries.
For example:
SELECT tblLeft.user_id,
tblLeft.purchase_id
FROM myview tblLeft
JOIN (SELECT user_id,
Count(*) AS purchases
FROM myview
GROUP BY user_id
HAVING purchases > 1) tblRight
ON tblLeft.user_id = tblRight.user_id
The tblRight is essentially a table containing the user_id's of all users with over 5 purchases.
We then do a select (tblLeft) and join it on the tbl right, ensuring only customers with over 5 purchases remain.

UNION All, Group BY and then get overall COUNT

I have 2 Tables..
User 1
user_id mobile_no
1 1111
2 2222
User 2
user_id mobile_no
1 3333
2 2222
I Want to first UNION These tables, then group by and then want to count total records
I am using this query but it's not working
SELECT COUNT(Q2.total) AS Overall
FROM (
SELECT COUNT(Q.user_id) AS total
FROM (
SELECT * FROM user1
UNION ALL
SELECT * FROM user2
) Q
GROUP BY Q.mobile_no
) Q2
if i user Inner Query e-g:
SELECT COUNT(Q.user_id) AS total
FROM (
SELECT * FROM user1
UNION ALL
SELECT * FROM user2
) Q
GROUP BY Q.mobile_no
I get these results, actually i want to again count these result...
total
2
1
1
i expect this result
Overall
3
This is weird. No one seems to have realised it's as simple as:
select count(*) overall
from (select mobile_no from user1 union select mobile_no from user2)
The difference between union and union all is that union removes duplicates.
Assuming that you are looking for the distinct number of mobile numbers:
select count(distinct mobile_no) as Overall
from (
select user_id, mobile_no
from user1
union all
select user_id, mobile_no
from user2
) a
select count (distinct mobile_no) from
(select user_id, mobile_no from user1 u1
UNION ALL
select user_id, mobile_no from user2 u2
) X
group by X.mobile_no
Rather use UNION and not UNION ALL
SQL UNION Operator
The UNION operator selects only distinct values by default. To allow
duplicate values, use the ALL keyword with UNION.
SELECT COUNT(mobile_no) Overall
FROM (
SELECT
mobile_no
FROM User1
UNION
SELECT
mobile_no
FROM User2
) Q
EDIT:
As #Bohemian correctly stated, no need for the distinct.
Try this:
SELECT COUNT(*) FROM
( (SELECT * FROM user1) UNION
(SELECT user_id as u1,mobile_no as m1
FROM user2) ) as a1 GROUP BY a1 .1

How to count the number of times a user_id is in a table?

Consider the following MySQL table:
user_id
-------
1
1
2
3
3
3
3
I would like an output of:
user_id cnt
-------------
1 2
2 1
3 4
I though this would make that happen, but it doesn't:
SELECT user_id, COUNT(1) FROM table GROUP BY user_id
What am I doing wrong?
SELECT user_id, COUNT(*) FROM table GROUP BY user_id;
btw, there is also the curiosity:
SELECT user_id, SUM(1) FROM table GROUP BY user_id
Both will give you the output you want.
Try this:
SELECT user_id, COUNT(user_id) as cnt FROM table GROUP BY user_id
SELECT user_id, count(user_id) as total FROM temp group by user_id;
The query produced this.
user_id total
-------------
1 2
2 1
3 4