Singular condition on an aggregate column - mysql

Slightly tough to define what I'm trying to get at, but taking a stab here. I'm working on redshift and writing a query on top of the following sample Table A:
User ID || Active_in_Month || Max_Months_On_Platform
1 1 6
1 2 6
1 5 6
2 1 3
2 3 3
After grouping by "Active_in_Month", I want to get at the following output in Table B:
Active_in_Month || Active_Distinct_Users || User_Cohorts
1 2 2
2 1 2
3 1 2
5 1 1
The "Active_Distinct_Users" is a simple COUNT(*). However, the calculation of "User_Cohorts" is where I'm stuck. The column is supposed to represent how many users were on the platform who have been active for at most the value in the "active_in_month" comlumn. For example, in Row 1 of Table B, there were two users who have "Max_Months_on_Platform" > 1 (Active in Month). In Row 5 of Table B there is only 1 "User_Cohort", because only 1 user has "Max Months on Platform" > 5 (Active_in_Month).
Hope this explains what I'm trying to get at.

Solution
Solved it using the following way, not sure if its the best way but it got the job done:
SELECT
Active_in_Month,
COUNT(DISTINCT user_id),
( SELECT
SUM(number_of_customers)
FROM (SELECT
tbl_a2.Max_Months_On_Platform AS total,
COUNT(DISTINCT tbl_a2.user_id) AS number_of_customers
FROM
tbl_a AS tbl_a2
GROUP BY tbl_a2.Max_Months_On_Platform
)
WHERE total + 1 >= tbl_a.Active_in_Month
) AS total_customers
FROM
tbl_a

I hope i have understand the correct rule to calculate the value of User_Cohorts. try this please:
SELECT
a.Active_in_Month
, COUNT(*) AS Active_Distinct_Users
, ( SELECT COUNT(DISTINCT user_id) +1
FROM tablea a2
WHERE a.Active_in_Month < a2.Max_Months_On_Platform
AND a.user_id <> a2.user_id
) AS User_Cohorts
FROM tablea a
GROUP BY a.Active_in_Month
ORDER BY a.Active_in_Month;
sample
MariaDB [test]> SELECT
-> a.Active_in_Month
-> , COUNT(*) AS Active_Distinct_Users
-> , ( SELECT COUNT(DISTINCT user_id) +1
-> FROM tablea a2
-> WHERE a.Active_in_Month < a2.Max_Months_On_Platform
-> AND a.user_id <> a2.user_id
-> ) AS User_Cohorts
-> FROM tablea a
-> GROUP BY a.Active_in_Month
-> ORDER BY a.Active_in_Month;
+-----------------+-----------------------+--------------+
| Active_in_Month | Active_Distinct_Users | User_Cohorts |
+-----------------+-----------------------+--------------+
| 1 | 2 | 2 |
| 2 | 1 | 2 |
| 3 | 1 | 2 |
| 5 | 1 | 1 |
+-----------------+-----------------------+--------------+
4 rows in set (0.00 sec)
MariaDB [test]>

Related

Displaying records where the same value have been mentioned more than 3 times in SQL

How can I find a value that has been mentioned several times in a row.
ID |1_Jan|3_Jan|4_Jan|4_Jan|
12 | 2 | 3 | 2 | 4 |
31 | 3 | 4 | 3 | 1 |
25 | 1 | 1 | 1 | 1 |
26 | 3 | 3 | 3 | 3 |
In the case of this table, I want to get out ID 25 and 26 because here the values 1 and 3 have been used 3 or more times in a record.
I was also wondering how can I for example only get out ID 25 even if 26 also has 3 or more?
You can select the rows with all equal column values, and then order by common column value:
with cte as (select t.id, t.1_Jan r, (t.1_Jan = t.2_Jan) and (t.2_Jan = t.3_Jan) and (t.3_Jan = t.4_Jan) val from test_table t)
select c.id from cte c where c.val = 1 order by c.r limit 1;
Output:
id
25
See demo.
This answers the original version of the question.
One way is to unpivot and aggregate:
select id, val, count(*)
from ((select id, 1_jan as val from t) union all
(select id, 2_jan as val from t) union all
(select id, 3_jan as val from t) union all
(select id, 4_jan as val from t)
) t
group by id, val
having count(*) >= 3;

How to select one row each conditions in MySQL?

I have a trouble with my code. I want to get only one rows each conditions in MySQL.
I have a table like that:
ID - Position - Content
1 2 abc
2 1 def
3 1 ghk
4 3 pol
5 2 lop
6 4 gty
So I want the result returned like: position = 1 -> highest id row then pass to position = 2 -> highest id row. I have no idea to code it.
Use a sub query to test the id
drop table if exists t;
create table t
(ID int, Position int, Content varchar(3));
insert into t values
(1 , 2 , 'abc'),
(2 , 1 , 'def'),
(3 , 1 , 'ghk'),
(4 , 3 , 'pol'),
(5 , 2 , 'lop'),
(6 , 4 , 'gty');
select t.*
from t
where t.id = (select min(id) from t t1 where t1.position = t.position);
+------+----------+---------+
| ID | Position | Content |
+------+----------+---------+
| 1 | 2 | abc |
| 2 | 1 | def |
| 4 | 3 | pol |
| 6 | 4 | gty |
+------+----------+---------+
4 rows in set (0.00 sec)
try this query..
SELECT DISTINCT * FROM table-name ORDER BY ID ASC;
DISTINCT operates on a single column. DISTINCT for multiple columns is not supported.
same column cant not print
And
order by id asc use and all record print 1 - n means minimum id
you can try like below query
SELECT t.*
FROM t
WHERE t.id IN (SELECT min(id) FROM t GROUP BY position);

mysql sum, CASE WHEN with GROUP BY

In MySQL, I want to sum the values ​​of certain statuses and display them in the same count column,
Do I have to give a condition to count ?!
status is 0, 1, 2 and 3, and status = 2 is a sum of 2, 3, 4 count values.
What kind of conditions should I give?
My Query:
SELECT A.STATUS, B.COUNT, B.REG_DT FROM
(SELECT 0 AS STATUS UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) A
LEFT JOIN (
SELECT STATUS , COUNT(*) AS COUNT, FROM TB_EXE WHERE reg_dt >= CURDATE()
GROUP BY STATUS
) B ON A.STATUS = B.STATUS
My Data:
status | count
-----------------
0 | 1
-----------------
1 | 2
-----------------
2 | 1
-----------------
3 | 0
-----------------
4 | 2
Expected Results:
status | count
-----------------
0 | 1
-----------------
1 | 2
-----------------
2 | 3
SELECT STATUS,COUNT(*)
FROM T
WHERE STATUS < 2
GROUP BY STATUS
UNION ALL
(SELECT 2,COUNT(*)
FROM T
WHERE STATUS >= 2
)
Where the 2 aggregations are dealt with separately.
+--------+----------+
| STATUS | COUNT(*) |
+--------+----------+
| 0 | 1 |
| 1 | 1 |
| 2 | 3 |
+--------+----------+
3 rows in set (0.00 sec)
Or more succinctly
select case when status > 1 then 2 else status end, count(*)
from t
group by case when status > 1 then 2 else status end
you can try like below using case when
select case when status>1 then 2 else status end as status,
sum(count) as cnt from t
group by status
Hmmm, I think I'd go with a framing solution on this one. IE something like this:
SELECT
Status,
Count,
SUM(Count) OVER(ORDER BY status ROWS
BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) AS FramedCount
FROM Status
this gives you a running total of the counts from all previous rows as the framed count. You can handle the logic in the application to determine which statuses should use the framed count OR you could handle it in the query by adding the following.
SELECT
status,
CASE
when status <= 3 THEN count
ELSE SUM(count) OVER(ORDER BY status ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
END AS 'MyCount'
FROM statusInfo

How to find the exact group that matches to defined values?

I simplified the table so it is easier to understand.
I have a table with groups and a group exists of multiple values. Here is the table:
VALUE | GROUP
A | 1
B | 1
A | 2
C | 2
B | 3
A | 4
B | 4
A | 5
B | 5
C | 5
I want to give values to my query wich I programmatically build and find the exact group that matches to these values.
For example if I give value A and B to my query I want as a result group 1 and 4
A ---------------> null
A and B ----------> 1 and 4
A , B and C ------> 5
B ---------------> 3
A and C ----------> 2
C ----------------> null
You can use a query like the following (assuming value,group pairs unique):
select `GROUP`
from MyTable
group by `GROUP`
having count(`VALUE`) = count(case when `VALUE` IN ('a','b') then 1 end)
and count(case when `VALUE` IN ('a','b') then 1 end) = #Count;
Where ('a','b') would be the list of values you are testing for, and #Count would be the count of different values in your check set (2 in this case).
Demo: http://www.sqlfiddle.com/#!2/78def/13

Select all rows with multiple occurrences

Ok, I have a single MySQL table with the name 'test' and 3 columns.
ID | playername | lastloginip
-----------------------------
1 | user 1 | 1
2 | user 2 | 2
3 | user 3 | 3
4 | user 4 | 4
5 | user 5 | 5
6 | user 6 | 1
7 | user 7 | 1
8 | user 8 | 2
Now, I would like to select ALL the rows where the lastloginip is found multiple times in the table, and then give the count of those rows.
In this case, it should return the number 5
as user 1, 2, 6, 7 and 8 have a lastloginip that is found multiple times.
I already tried using
SELECT COUNT(*)
FROM (
SELECT *
FROM test
GROUP BY lastloginip
HAVING COUNT(*) > 1
) t
But that gave back the number 2 instead of 5.
I am not sure how to set up this query correctly. Most of my findings on the internet keep showing only 2 rows or giving the number 2 instead of 5.
First COUNT(), then SUM():
SELECT SUM(occurences)
FROM
(
SELECT COUNT(*) AS occurences
FROM test
GROUP BY lastloginip
HAVING COUNT(*)>1
) t
Try this query.
SELECT SUM(loginip)
FROM(
SELECT
lastloginip,
COUNT(lastloginip)
as loginip
FROM test
GROUP BY lastloginip
HAVING COUNT(ID)>1
)t
You can fetch the sum of occurrences using the above code and if you want to view the records with multiple occurences, refer to the query below-
Select *
from test
where lastloginip in (
select *
from
(select lastloginip
from test
group by lastloginip
having count(lastloginip)>1
)
as a)