Query to find users with one row in table - mysql

I have a table "users" which has multiple columns in which column "status" has multiple values like 1,0,3,2,4. There is column "user_id" which doesn't contain unique values since, this is foreign key of another table called "user_master".
so here in "users" table we have multiple values of the one user.
So, Here is my actual query is that i would like to write a sql query to find users has only one entry in table "users" with particular status value.
For e.g. I would like to fetch all such users with status=2 and their entry in table is not more than 1. Like if user has multiple entries with status 2,1,4 in table which should not be return in query.
It should yield those users which has only one entry in table and which is of status = 2

That must be what you use:
Select count(u.user_id) AS cnt, u.*
from user u
where u.status = 2
group by u.user_id, u.status
having cnt = 1;

WITH tmp AS(
SELECT Stud_Id,COUNT(*) AS 'Count' FROM Student_tbl GROUP BY Stud_Id
)
SELECT * FROM tmp WHERE Count = 1 AND Status = 2
You have to add field in GROUP BY Clause whichever you want to use in SELECT clause.

I have researched it and found answer for it.
And query goes like this.
select count(id) as cnt,
user_id,status from users
group by user_id
having cnt < 2 and status=2
First it will group the things having count less than 2 and then which will check for status.

Related

Delete a MySQL selection

I would like to delete my MySQL selection.
Here is my MySQL selection request:
SELECT *
FROM Items
WHERE id_user=1
ORDER
BY id_user
LIMIT 2,1
With this working request, I select the third item on my table which has as id_user: 1.
Now, I would like to delete the item that has been selected by my request.
I am looking for a same meaning request which would look like this :
DELETE FROM Items (
SELECT * FROM Items WHERE id_user=1 ORDER BY id_user LIMIT 2,1
)
The first thing to note is that there is an issue with your query. You are filtering on a unique value of id_user and sorting on the same column. As all records in the resultset will have the same id_user, the actual order of the resultset is undefined, and we cannot reliably tell which record comes third.
Assuming that you have another column to disanbiguate the resultset (ie some value that is unique amongst each group of records having the same id_user), say id, here is a solution to your question, that uses a self-join with ROW_NUMBER() to locate the third record in each group.
DELETE i
FROM items i
INNER JOIN (
SELECT
id,
id_user,
ROW_NUMBER() OVER(PARTITION BY id_user ORDER BY id) rn
FROM items
) c ON c.id = i.id AND c.id_user = i.id_user AND c.rn = 3
WHERE i.id_user=1 ;
Demo on DB Fiddle
You didn't provide the definition of your table. I guess it has a primary key column called id.
In that case you can use this
CREATE TEMPORARY TABLE doomed_ids
SELECT id FROM Items WHERE id_user = 1 ORDER BY id_user LIMIT 2,1;
DELETE FROM Items
WHERE id IN ( SELECT id FROM doomed_ids);
DROP TABLE doomed_ids;
It's a pain in the neck, but it works around the limitation of MySQL and MariaDB disallowing LIMITs in ... IN (SELECT ...) clauses.
You can use the select query to create a derived table and join it back to your main table to determine which record(s) to delete. Derived tables can use the limit clause.
Assuming that the PK is called id, the query would look as follows:
delete i from items i
inner join (SELECT id FROM Items
WHERE id_user=1
ORDER BY id_user LIMIT 2,1) i2 on i.id=i2.id
You need to substitute your PK in place of id. If you have a multi-column PK, then you need to select all the PK fields in the derived table and join on all of them.

MYSQL - Count total of rows from multiple tables with same column name

I have three tables: a_survey, b_survey and c_survey. Each of these tables have a column_name "user_id". What I want to do is count the actual posted surveys and return that value in a single row. So, if there was found one record with the matching user_id for each of these tables, the count would return 3.
Here's what I've tried:
select count(user_id) AS total_of_surveys
FROM a.survey, b.survey, c.survey
WHERE user_id = 3;
but I'm getting error:
Column 'user_id' in field list is ambiguous
Thanks in advance!
select sum(count(a.survey.user_id)+count(b.survey.user_id)+count(c.survey.user_id)) AS total_of_surveys
FROM a.survey, b.survey, c.survey
WHERE user_id = 3;
What you have tried was a cartesian plan it will multiply the result by the quantity of registries on each table.
The right way to do what you want is to join (with left join) or 'UNION' the tables like:
select count(user_id) from
(select user_id from a_survey where user_id = 3 UNION ALL
select user_id from b_survey where user_id = 3 UNION ALL
select user_id from c_survey where user_id = 3) tables
You will need to count each table seperately and sum it together. You can do this with one (ugly) query if you want. Something like this should work:
Select (select count(user_id) FROM a.survey WHERE user_id = 3) + (select count(user_id) FROM b.survey WHERE user_id = 3) + (select count(user_id) FROM c.survey WHERE user_id = 3) as total_of_surveys;

MySQL get most recent entries from a big table

I have a table with more than 50k entries and a few users:
transactions Table:
ID
USER
VALUE
TIMESTAMP
users Table:
USER
TYPE
REGION
I would like to get the most recent transactions for each user. So far I am using the following GROUP BY statement, but it is slow (takes 5-10sec approx):
select ID , max(TIMESTAMP) as TIMESTAMP from transactions group by USER;
Is there a faster statement to retrieve the most recent entries?
First of all as per my understanding ID columns should keep unique values in transaction table so group by should be on USER field as per your requirement.
Further you can try below query. I am not sure but you can compare its time with your query and use accordingly.
SELECT
USER , TIMESTAMP
FROM
(SELECT USER,TIMESTAMP FROM transactions ORDER BY ID DESC) a
GROUP BY USER;
Assuming there will be an index on USER column as this is common between both tables.
Try this,
select u.*,tr.* from users as u
outer apply
(
select top 1 * from transactions as t
where t.USER= u.USER
order by t.ID desc
)as tr

Select Data From Table Without Multiple Of The Same User ID

I am trying to select all the elements where x_id=1 but there will be multiple rows for that result with the same user_id and I just want it to show one result for each user id (instead of multiple). How would I be able to do this in SQL im completely lost?
Table:
a
id | x_id | user_id
SELECT DISTINCT user_id FROM table WHERE x_id = 1;
select distinct user_id from a where x_id = 1;
SELECT a.user_id
FROM a a
WHERE a.x_id = 1
GROUP BY a.user_id
-- or --
SELECT DISTINCT a.user_id
FROM a a
WHERE a.x_id = 1
These return an equivalent result set. My personal preference is to use the GROUP BY, because I sometimes want to return a count of the number of rows, or use some other aggregate function, which I can't do with the DISTINCT.

How do I write a SQL query to detect duplicate primary keys?

Suppose I want to alter the table so that my primary keys are as follows
user_id , round , tournament_id
Currently there are duplicates that I need to clean up. What is the query to find all duplicates?
This is for MySQL and I would like to see duplicate rows
Technically, you don't need such a query; any RDBMS worth its salt will not allow the insertion of a row which would produce a duplicate primary key in the table. Such a thing violates the very definition of a primary key.
However, if you are looking to write a query to find duplicates of these groups of columns before applying a primary key to the table that consists of these columns, then this is what you'd want:
select
t.user_id, t.round, t.tournament_id
from
table as t
group by
t.user_id, t.round, t.tournament_id
having
count(*) > 1
The above will only give you the combination of columns that have more than one row for that combination, if you want to see all of the columns in the rows, then you would do the following:
select
o.*
from
table as o
inner join (
select
t.user_id, t.round, t.tournament_id
from
table as t
group by
t.user_id, t.round, t.tournament_id
having
count(*) > 1
) as t on
t.user_id = o.user_id and
t.round = o.round and
t.tournament_id = o.tournament_id
Note that you could also create a temporary table and join on that if you need to use the results multiple times.
SELECT name, COUNT(*) AS counter
FROM customers
GROUP BY name
HAVING COUNT (*) > 1
That's what you are looking for.
In table:
ID NAME email
-- ---- -----
1 John Doe john#teratrax.com
2 Mark Smith marks#teratrax.com
3 John Doe jdoe#company.com
will return
name counter
---- -------
John Doe 2
Assuming you either have a table with those three columns, or that you can make and populate a table with those three columns, this query will show the duplicates.
select user_id, round, tournament_id
from yourtable
group by user_id, round, tournament_id
having count(*) > 1
This query selects all rows from the customers table that have a duplicate name but also shows the email of each duplicate.
SELECT c.name, c.email FROM customers c, customers d
WHERE c.name = d.name
GROUP BY c.name, c.email
HAVING COUNT(*) > 1
The downside of this is that you have to list all the columns you want to output twice, once in the SELECT and once in the GROUP BY clause. The other approach is to use a subquery or join to filter the table against the list of known duplicate keys.