Select all rows with multiple occurrences - mysql

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)

Related

MySQL - select distinct value from two column

I have a table with the following structure:
IdM|IdS
-------
1 | 2
1 | 3
1 | 4
2 | 1
2 | 3
2 | 4
3 | 1
3 | 2
3 | 3
3 | 4
How could I make a select statement on this table, which will return some rows of this table, where in each row, a specific id appears only one, indifferent on which column it is specified?
For the above result set, I would like a query that would return:
-------
1 | 2
3 | 4
-------
To give another example, if you would omit the first row in the original dataset:
IdM|IdS
-------
1 | 3
1 | 4
2 | 1
2 | 3
2 | 4
3 | 1
3 | 2
3 | 3
3 | 4
the result set should be:
-------
1 | 3
2 | 4
-------
That's actually an interesting problem. If I follow you correctly, you want to iterate through the dataset and only retain rows where both values were never seen before. You could use a recursive query:
with recursive
data as (
select idm, ids, row_number() over(order by idm, ids) rn
from mytable
where idm <> ids
),
cte as (
select idm, ids, rn, 1 as to_keep , concat(idm, ',', ids) visited from data where rn = 1
union all
select d.idm, d.ids, d.rn,
(not find_in_set(d.idm, c.visited) and not find_in_set(d.ids, c.visited)),
case when (not find_in_set(d.idm, c.visited) and not find_in_set(d.ids, c.visited))
then concat_ws(',', c.visited, d.idm, d.ids)
else c.visited
end
from cte c
inner join data d on d.rn = c.rn + 1
)
select idm, ids from cte where to_keep
The first CTE enumerates the rows ordered by both columns. Then the recursive query walks the resultset, checks if both values are new, and sets a flag accordingly of the columns. Flagged numbers are retained to be used for filtering in the following iteration.
Demo on DB Fiddle
Note that, given your requirement, not all values may appear in the resultset. Consider the following dataset:
idm ids
+-----+---
1 2
1 3
1 4
Your logic will only return the first row.

Select previous record from row

Example
id |u_id
1 | 1
2 | 1
3 | 2
4 | 1
5 | 2
6 | 3
I know, the id 4 has u_id of 1, but I want to select the last row having u_id 1 before that with id 4 i.e. I want to select the row with the id 2.
Note that I don't know this id.
How can I achieve that?
This is what the result should look like:
id |u_id
2 | 1
4 | 1
select * from table where uid=1 order by id desc limit 2
This may help you.
SELECT * FROM ( SELECT * FROM yourTable WHERE u_id=1 ORDER BY id DESC LIMIT 2) AS tab ORDER BY tab.id ASC
Finally figured out the correct sql query for it.
SELECT * FROM table WHERE u_id = 1 AND (id = 4 OR id < 4) ORDER BY id DESC LIMIT 0,2
If you are using a fairly recent version of MySQL, what you need is the LAG() windowed function:
SELECT id,
u_id,
LAG(id) OVER W AS prev_id
FROM MyTable
WINDOW w AS (PARTITION BY u_id ORDER BY id)
ORDER BY id, u_id;
It will produce a result like this:
id |u_id |prev_id
1 | 1 | null
2 | 1 | 1
3 | 2 | null
4 | 1 | 2
5 | 2 | 3
6 | 3 | null
You can play with the query here.
As your title states:
select previous record from row
The following gives you every row that comes prior to a 2, and will work with more than just the data you've shown in your example:
SELECT *
FROM example
WHERE id IN (
SELECT id - 1
FROM example
WHERE u_id = 2);
[SEE DEMO HERE]

mysql query for multiple fields

I am using mysql for survey answers.
the schema of the survey table is as follows:
id | rating1 | rating2 | rating3 | rating4 | .... | rating20 |
1 10 10 2 8 .... 4
2 8 8 8 5 .... 7
As you can see, there's rating scores (from 1 to 10) inserted into rating1 - rating20 fields.
I can easily find biggest or smallest scores from rating(1-20) fields for each row using this query: "SELECT greatest(rating1, rating2 .. rating20) FROM TBL_SURVEY WHERE id=1" which returns 10 for id 1.
But I don't know that greatest score belongs which field. And I like to count distnct rating scores. How many 10s or any other scores from rating1-rating20 fields for id 1?
Is there mysql queries for this? or Is there a way to get what I want using php?
Any help would be very appreciated...
I'm going to suggest that you change your table design to something like this:
id | rating_id | rating
1 | 1 | 10
1 | 2 | 10
1 | 3 | 2
1 | 4 | 8
etc.
With this improved and normalized design, we can find the max rating and its corresponding rating_id using a query like this:
SELECT t1.*
FROM ratings t1
INNER JOIN
(
SELECT id, MAX(rating) AS max_rating
FROM ratings
GROUP BY id
) t2
ON t1.id = t2.id AND
t1.rating = t2.max_rating
For your second question of e.g. how many 10s there are for id 1 we could use this:
SELECT COUNT(*)
FROM ratings
WHERE id = 1 AND rating = 10

Singular condition on an aggregate column

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]>

Count values in MySQL with specific ID

Ok, this should be simple:
ID | version | downloads
========================
1 | 1.0 | 2
1 | 1.1 | 4
1 | 1.2 | 7
1 | 1.3 | 3
2 | 1.0 | 3
2 | 2.0 | 3
2 | 3.0 | 13
I like to get the downloads of a specific product (ID) no matter which version.
This doesn't work
SELECT COUNT(*) AS downloads FROM table WHERE ID = 1
should return 2 + 4 + 7 + 3 = 16
Your output says that you want to sum the downloads column.
so you have to use sum aggregate function..
SELECT Sum(downloads) AS downloads FROM table WHERE ID = 1
If you want sum(downloads) for each ID,Just change the query as follow
SELECT ID,Sum(downloads) AS downloads FROM table group by ID
If you need total record counts then only use Count
SELECT Count(*) AS count FROM table WHERE ID = 1
SELECT SUM(downloads) FROM table WHERE ID = 1;
Try
SELECT SUM(downloads) AS downloads
FROM table
WHERE id = 1
Sum adds the values
You can also use group by to return the sum for each id
SELECT SUM(downloads) AS downloads
FROM table
GROUP BY id
I would go for a query that could show you all SUMs from all IDs then if you need you filter one in specific.
SELECT id,
SUM(downloads) as TotalDownloads
FROM table
GROUP BY id;
If you need to filter a specific id just add where id = 1
The result for this would be:
ID | TotalDownloads
========================
1 | 16
2 | 19