Need a SQL query statement for this case - mysql

This is the structure of the table
mysql> select * from p1;
+----------+-------+-----------+
| username | token | last_used |
+----------+-------+-----------+
| a | aacs | 5 |
| d | dddd | 3 |
| a | aaaaa | 3 |
+----------+-------+-----------+
How can I delete the record who has the minimum last_used value from the set queried by username?
In this case ,the given username parameter is 'a',then I shold delete the record 'a','aaaaa',3 because 3 is smaller than 5(the username of last_used(5) is 'a',too).
My answer is
delete from persistent_logins
where last_used=(select *
from (select MIN(last_used)
from persistent_logins where username=?)as t
)
and username=?
but it's useful,I need a statement like delete .... from..where username=?
It is important that only one parameter is allowed.But my answer has two parameter.

You can actually use ORDER BY and LIMIT with DELETE. The rows will be deleted in that order with LIMIT controlling how many are deleted.
If the ORDER BY clause is specified, the rows are deleted in the order that is specified. The LIMIT clause places a limit on the number of rows that can be deleted.
(From: https://dev.mysql.com/doc/refman/5.0/en/delete.html)
Try something like this:
DELETE FROM p1
WHERE username = ?
ORDER BY last_used ASC
LIMIT 1

Related

Search for duplicates, then assign value to another column based on which has the highest value in a separate column

I need to look for duplicates in my table, then check to see which has the highest age, update the oldest column with which one of them is the oldest, by replacing with their name.
+---------+-----+--------+
| Name | Age | Oldest |
+---------+-----+--------+
| John | 22 | NULL |
| John | 25 | NULL |
| James1 | 34 | NULL |
+---------+-----+--------+
You will find your duplicates with this select statement
SELECT name FROM your_table
GROUP BY name
Having COUNT(name) > 1
result "John"
This will result in a list (of one in this case) of duplicate names.
Then you may use this update statement to obtain the result you are looking for:
UPDATE your_table
SET oldest = name
WHERE name = 'John'
AND age IN (SELECT MAX(age) FROM your_table WHERE name = 'John'
In this particular case, you need to do the process manually running the update statement once for each duplicate that you found with the duplicate select query.
In any case, it would be convenient that your table had an identification column such an id (INT)column. This two step process may be further develop in a stored procedure.

Retrieve rows in which a column doesn't contain a value

I have a MySQL table like below:
| ID | userIDs
---------------
| 1 | 4,3,5
| 2 | 2,3
| 3 | 1,2,3
I want to retrieve all the rows in which userIDs doesn't contain 1.
I tried
SELECT * FROM tablename WHERE 1 NOT IN (userIDs)
But it's not working.
Use FIND_IN_SET
SELECT * FROM tablename
WHERE find_in_set(1, userIDs) = 0
But actually you should rather change your table design. Never store multiple values in a single column!

Getting a set with unique column values from MySQL

Say that I have a set with columns like this
user_id | username | updated_at | data...
user_id and username are not unique in the set, so you can have something like this
user_id | username | updated_at | data...
------------------------------------------
1 | test | 140****** | ...
4 | test2 | 140****** | ...
1 | test | 139****** | ...
7 | meh | 140****** | ...
But I would like to remove the duplicate occurrences; I tried GROUP BY but it gives me something unexpected as a lot of items are getting removed (I guess they appears later in the set as the query has a LIMIT in it).
If you need to select all the data - first of all u should decide how to get the updated_at and data columns.
In case you want to have the data concatenated and you want to have the latest updated_at you should do
SELECT user_id, username, max(updated_at), group_concat(data separator ',')
FROM table_name
GROUP BY user_id, username
ORDER BY user_id, username
LIMIT X
in that case your data will be ordered by user_id, and username
Note:
it is not clear from your question if you want to remove the data from the table itself or only from the result set.
Is this what you want?
select distinct user_id, username
from table t;

Counting votes in a MySQL table only once or twice

I've got the following table:
+-----------------+
| id| user | vote |
+-----------------+
| 1 | 1 | text |
| 2 | 1 | text2|
| 3 | 2 | text |
| 4 | 3 | text3|
| 5 | 2 | text |
+-----------------+
What I want to do is to count the "votes"
SELECT COUNT(vote), vote FROM table GROUP BY vote
That works fine. Output:
+-------------------+
| count(vote)| vote |
+-------------------+
| 3 | text |
| 1 | text2|
| 1 | text3|
+-------------------+
But now I only want to count the first or the first and the second vote from a user.
So result what I want is (if I count only the first vote):
+-------------------+
| count(vote)| vote |
+-------------------+
| 2 | text |
| 1 | text3|
+-------------------+
I tried to work with count(distinct...) but can get it work.
Any hint in the right direction?
You can do this in a single SQL statement with something like this:
SELECT vote, COUNT(vote)
FROM
(
SELECT MAX(user), vote
FROM table1
GROUP BY user
) d
GROUP BY vote
Note that this only gives you 1 vote not 1 or 2.
The easiest way would be to use one of the "row numbering" solutions listed in this SO question. Then your original query's almost there:
SELECT
COUNT(vote),
vote
FROM tableWithRowNumberAdded
WHERE MadeUpRowNumber IN (1,2)
GROUP BY vote
My alternative is much longer winded and calls for working tables. These can be "real" tables in your schema, or whatever flavour of intermediate resultsets you are comfortable with.
Start by getting the first vote for each user:
SELECT user, min(id) FROM table GROUP BY user
Put this in a working table; let's call it FirstVote. Next we can get each user's second vote, if any:
SELECT user, min(id) FROM table WHERE id not in (select id from FirstVote) GROUP BY user
Let's call the result of this SecondVote. UNION FirstVote to SecondVote, join this to the original table and group by vote. There's your answer!
SELECT
vote,
COUNT(*)
FROM table
INNER JOIN
(
SELECT id FROM FirstVote
UNION ALL
SELECT id FROM SecondVote
) as BothVotes
ON BothVotes.id = table.id
GROUP BY vote
Of course it could be structured as a single statement with multiple sub-queries but that would be horrendous to maintain, or read in this forum.
This is a very triky question for MySQL. On other systems there windowed functions: it performs a calculation across a set of table rows that are somehow related to the current row.
MySQL lacks this functionality. So one should look for a workaround. Here is the problem description and couple solutions suggested: MySQL and window functions.
I also assume that first 2 votes by the User can be determined by Id: earlier vote has smaller Id.
Based on this I would suggest this solution to your problem:
SELECT
Vote,
Count (*)
FROM
Table,
(
SELECT
user_id, SUBSTRING_INDEX(GROUP_CONCAT(Id ORDER BY user_id ASC), ',', 2) AS top_IDs_per_user
FROM
Table
GROUP BY
user_id
) s_top_IDs_per_User
WHERE
Table.user_id = s_top_IDs_per_User.User_id and
FIND_IN_SET(Id, s_top_IDs_per_User.top_IDs_per_user)
GROUP BY Vote
;

filter sql rows using update statement

I am trying to write a query which can get invalid refby(is related to id), please check following db structure...
| id | acnumber | refby |
+----+-----------+--------+
| 1 | ac01 | 2 |
+----+-----------+--------+
| 2 | ac02 | 1 |
+----+-----------+--------+
| 3 | ac03 | 5 |
+----+-----------+--------+
As you can find there is no id with value of 5 in above table so query must return 3rd row as result.
I have tried...
SELECT * FROM tbl.members WHERE refby != (SELECT id FROM tbl.members WHERE id = refby)
But this is not giving correct results, please help, thanks.
SELECT * FROM members WHERE refby not in (SELECT id FROM members)
This should solve your problem
You can try this using not in:-
SELECT * FROM tbl.members WHERE refby not in (SELECT id FROM members)
This should be a LEFT JOIN, NOT IN is slow on large tables... assuming id and refid is an PRIMARY KEY or UNIQUE key (read unique within your dataset) then this query should return the same results.
SELECT
*
FROM
members members1
LEFT JOIN
members members2
ON members1.id = members2.refby
WHERE members2.id IS NULL
check the sqlfriddle http://sqlfiddle.com/#!2/05731/1