How to make a query to get only records with the same screen_name and skip=0 value?
---------------------------
| id | screen_name | skip |
---------------------------
| 1 | mary | 0 |
| 2 | john | 0 |
| 3 | tom | 1 |
| 4 | mary | 0 |
| 5 | ben | 1 |
| 6 | john | 1 |
---------------------------
SELECT screen_Name
FROM tableName
WHERE skip = 0
GROUP BY screen_name
HAVING COUNT(*) > 1
SQLFiddle Demo
UPDATE
if you want to get all records not just the screen_name, use JOIN instead of IN
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT screen_Name
FROm tableName
WHERE skip = 0
GROUP BY screen_name
HAVING COUNT(*) > 1
) b ON a.screen_name = b.screen_name
SQLFiddle Demo
For faster performance, add an INDEX on column screen_name for faster performance.
ALTER TABLE tableName ADD INDEX index_name (screen_Name)
You coud try to use:
select id,screen_name,skip
from TABLE
where skip=0
and screen_name in (select t2.screen_name
from TABLE t2
group by t2.screen_name
having count(*)>1
)
This will give you all the records with skip=0 and a repeated screen_name
Related
in my table having data like this
+-----+----------+
| sno | name |
+-----+----------+
| 101 | Raju |
| 102 | Raju |
| 103 | Santhosh |
| 104 | Santhosh |
| 105 | madhavi |
| 106 | suheel |
+-----+----------+
in that i want find dupliacte records and display sno(number) only
for example output should be like this
+-----+
| sno |
+-----+
| 101 |
| 102 |
| 103 |
| 104 |
+-----+
In a Derived table, get all the name values which have duplicates. To do that, we can GROUP BY on name and use HAVING to consider only those names, where COUNT(*) (total number of rows for that name) is more than 1.
Now, we can join back to the main table to get their respective sno values
SELECT
t.sno
FROM your_table t
JOIN (SELECT name
FROM your_table
GROUP BY name
HAVING COUNT(*) > 1) dt
ON dt.name = t.name
Here is a MySQL 8+ way of doing this:
SELECT sno
FROM
(
SELECT t.*, COUNT(*) OVER (PARTITION BY name) cnt
FROM yourTable t
) t
WHERE cnt > 1;
You can try using correlated subquery
select sno from tablename a
where name in (select 1 from tablename b where a.name=b.name having count(name)>1 )
Apologies if the answer is dead obvious but in spite of a lot of research and trying out different commands, the solution escapes me (I'm more of a lexicographer than a dev).
We have a table which for various reasons has ended up with some rows which have duplicated values in critical cells. A mockup looks like this:
Unique_ID | E_ID | Date | User_ID | V_value
1 | 500 | 2012-05-12 | 23 | 3
2 | 501 | 2012-05-12 | 23 | 3
3 | 501 | 2012-05-13 | 23 | 1
4 | 502 | 2012-05-13 | 23 | 2
5 | 503 | 2012-05-12 | 23 | 2
6 | 7721 | 2012-05-22 | 8845 | 3
7 | 7722 | 2012-05-22 | 8845 | 3
8 | 7722 | 2012-05-22 | 8845 | 3
9 | 7723 | 2012-05-22 | 8845 | 3
So the rows I need as output are Unique_ID 2 & 3 and 7 & 8 as they are identical as regards the E_ID and User_ID field. The values of the other fields are not relevant to our problem. So what I want is this, ideally:
Unique_ID | E_ID | Date | User_ID | V_value
2 | 501 | 2012-05-12 | 23 | 3
3 | 501 | 2012-05-13 | 23 | 1
7 | 7722 | 2012-05-22 | 8845 | 3
8 | 7722 | 2012-05-22 | 8845 | 3
For reasons to do with the data, I need the output to appear with the Edit features (in particular the tick-box or at least the Delete feature) because I need to go through the table manually and discard one or the other duplicate based on decisions/conditions that can't be determined with SQL commands.
The closest I have come is this:
SELECT *
FROM ( SELECT E_ID, User_ID, COUNT(Unique_ID)
AS V_Count
FROM TableName
GROUP BY E_ID, User_ID
ORDER BY E_ID )
AS X
WHERE V_Count > 1
ORDER BY User_ID ASC, E_ID ASC
which does give me the rows with the duplications but because I'm creating the V_Count column to give me the duplicates:
E_ID | User_ID | V_Count
501 | 23 | 2
7722 | 8845 | 2
the output does not give me the Delete option I need - it says it's because there is no unique ID and I get that, as it puts them together in the same row. Is there a way to do this without losing the Unique_ID so I don't lose the Delete function?
You can use aggregation to check for a given user_id and e_id if there are more than one rows. Then join it with your table to get all the columns in the result.
select t1.*
from tablename t1
join (
select e_id,
user_id
from tablename
group by e_id,
user_id
having count(*) > 1
) t2
on t1.e_id = t2.e_id
and t1.user_id = t2.user_id
Which can be more cleanly expressed using the USING clause as:
select *
from tablename t1
join (
select e_id,
user_id
from tablename
group by e_id,
user_id
having count(*) > 1
) t2 using (e_id, user_id)
A sort-of simple method uses exists:
select t.*
from tablename t
where exists (select 1
from tablename t2
where t2.e_id = t.e_id and t2.date = t.date and
t2.user_id = t.user_id and t2.v_value = t.v_value and
t2.unique_id <> t.unique_id
);
An alternative way that puts each combination on a single row with all the ids is:
select e_id, date, user_id, v_value,
group_concat(unique_id) as unique_ids
from tablename t
group by e_id, date, user_id, v_value
having count(*) > 1;
This is the code i got so far
SELECT users_ID,Problem_ID
FROM 'submission'
WHERE Status = "AC"
GROUP BY users_ID,Problem_ID
I am getting these results
+----------+------------+
| Users_ID | Problem_ID |
+----------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
+----------+------------+
I only want to get
+----------+------------+
| Users_ID | Problem_ID |
+----------+------------+
| 1 | 3 | -- so because there are 3 results for user_ID 1
| 2 | 2 | -- and there are 2 results for user_ID 2
+----------+------------+
So the Problem_ID is how many rows I am getting from my query for each user.
But how do I accomplish this?
Edit:
I forgot mention that the table contains duplicates of the same problem for example.
I got a Problem with the ID of 1 and then in the database there could be two rows with the same user and with status as "AC" but I want to only get one of them.
SELECT users_ID, count(Problem_ID) as `problem_count`
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID;
This should work:
SELECT users_ID, COUNT(DISTINCT Problem_ID)
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID
You can do something like this :
SELECT
s.users_ID
,count(s.Problem_ID)+CASE WHEN IFNULL(userDupli.nbrUserAC, 0) > 0 THEN 1 ELSE 0 END as `problem_count`
FROM
`submission` s
left join (SELECT
users_ID
,count(*) as nbrUserAC
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID) userDupli
on userDupli.users_ID = s.users_ID
WHERE
Status <> 'AC'
GROUP BY
users_ID
,userDupli.nbrUserAC
Say if I have a table similar to this but including more columns and more rows (These are the only relevant ones):
+-------+----+
| name | id |
+-------+----+
| james | 1 |
| james | 2 |
| james | 3 |
| adam | 4 |
| max | 5 |
| adam | 6 |
| max | 7 |
| adam | 8 |
+-------+----+
How could I get it so that it would only show the max(id) from each name like:
+-------+----+
| name | id |
+-------+----+
| adam | 8 |
| max | 7 |
| james | 3 |
+-------+----+
I currently just have this
"select * from table order by id desc"
but this just shows the latest ids. I only want to be able to see one of each name.
So basically show only the highest id of each name
You would use aggregation and max():
select name, max(id)
from table t
group by name
order by max(id) desc
limit 40;
EDIT:
If you need select * with the highest id, then use the not exists approach:
select *
from table t
where not exists (select 1 from table t2 where t2.name = t.name and t2.id > t.id)
order by id desc
limit 40;
The "not exists" essentially says: "Get me all rows in the table where there is no other row with the same name and a higher id". That is a round-about way of getting the maximum row.
One way to achieve this is to leverage a non-standard GROUP BY extension in MySQL
SELECT *
FROM
(
SELECT *
FROM table1
ORDER BY id DESC
) q
GROUP BY name
-- LIMIT 40
or another way is to grab a max id per name first and then join back to your table to fetch all other columns
SELECT t.*
FROM
(
SELECT MAX(id) id
FROM table1
GROUP BY name
-- LIMIT 40
) q JOIN table1 t
ON q.id = t.id
ORDER BY name;
Output:
| NAME | ID |
|-------|----|
| adam | 8 |
| james | 3 |
| max | 7 |
Here is SQLFiddle demo
I have a table that holds usernames and results.
When a user insert his results to the DB, I want to execute a query that will return
the top X results ( with their rank in the db) and will also get that user result
and his rank in the DB.
the result should be like this:
1 playername 4500
2 otherplayer 4100
3 anotherone 3900
...
134 current player 140
I have tried a query with union, but then I didnt get the current player rank.
ideas anyone?
The DB is MYSQL.
10x alot and have agreat weekend :)
EDIT
This is what I have tried:
(select substr(first_name,1,10) as first_name, result
FROM top_scores ts
WHERE result_date >= NOW() - INTERVAL 1 DAY
LIMIT 10)
union
(select substr(first_name,1,10) as first_name, result
FROM top_scores ts
where first_name='XXX' and result=3030);
SET X = 0;
SELECT #X:=#X+1 AS rank, username, result
FROM myTable
ORDER BY result DESC
LIMIT 10;
Re your comment:
How about this:
SET X = 0;
SELECT ranked.*
FROM (
SELECT #X:=#X+1 AS rank, username, result
FROM myTable
ORDER BY result DESC
) AS ranked
WHERE ranked.rank <= 10 OR username = 'current';
Based on what I am reading here:
Your table structure is:
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name | varchar(50) | YES | | NULL | |
| result | int(11) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
Table Data looks like:
+---------+--------+
| name | result |
+---------+--------+
| Player1 | 4500 |
| Player2 | 4100 |
| Player3 | 3900 |
| Player4 | 3800 |
| Player5 | 3700 |
| Player6 | 3600 |
| Player7 | 3500 |
| Player8 | 3400 |
+---------+--------+
You want a result set to look like this:
+------+---------+--------+
| rank | name | result |
+------+---------+--------+
| 1 | Player1 | 4500 |
| 2 | Player2 | 4100 |
| 3 | Player3 | 3900 |
| 4 | Player4 | 3800 |
| 5 | Player5 | 3700 |
| 6 | Player6 | 3600 |
| 7 | Player7 | 3500 |
| 8 | Player8 | 3400 |
+------+---------+--------+
SQL:
set #rank = 0;
select
top_scores.*
from
(select ranks.* from (select #rank:=#rank+1 AS rank, name, result from ranks) ranks) top_scores
where
top_scores.rank <= 5
or (top_scores.result = 3400 and name ='Player8');
That will do what you want it to do
assuming your table has the following columns:
playername
score
calculated_rank
your query should look something like:
select calculated_rank,playername, score
from tablename
order by calculated_rank limit 5
I assume you have PRIMARY KEY on this table. If you don't, just create one. My table structure (because you didn't supply your own) is like this:
id INTEGER
result INTEGER
first_name VARCHAR
SQL query should be like that:
SELECT #i := #i+1 AS position, first_name, result FROM top_scores, (SELECT #i := 0) t ORDER BY result DESC LIMIT 10 UNION
SELECT (SELECT COUNT(id) FROM top_scores t2 WHERE t2.result > t1.result AND t2.id > t1.id) AS position, first_name, result FROM top_scores t1 WHERE id = LAST_INSERT_ID();
I added additional condition into subquery ("AND t2.id > t1.id") to prevent multiple people with same result having same position.
EDIT: If you have some login system, it would be better to save userid with result and get current user result using it.