How to remove duplicates correct? - php

I have a MySQL chart table like this : PRIMARY KEY(ID), Name, Value, Date
I need to remove duplicates if "Name AND Value AND Date" are the same as existing row.
I have beneath a solution i found while ago and which worked (not 100%), but I don't understand the command in it's total because I'm only into BASIC MySQL... Can somebody explain me a little further...
definitely what is the x at the end ???
$delDups = "delete from chart where id not in (select * from (select min(id) from chart n group by value) x)";
mysql_query($delDups);

It appears to me that you could do it simpler, like this:
$delDups = "delete from chart where id not in (select min(id) from chart n group by value)";
In the subquery you are saing:
" Hey, take all the values and find the minimun id for the group of values"
So, imagine the result of the subquery as a list, like "(12, 13, 200)".. the NOT IN operator will take that list and use it to filter the result of the upper query and say "Give me all the results, less the ones where id is in this list"
I'm not sure if I explained it as expected...

You could add an unique key for all 3 columns:
ALTER IGNORE TABLE my_table
ADD CONSTRAINT uc_unic UNIQUE (Name, Value, Date)
As to that x,mysql permit aliases,essentially name shortcuts for convenience.

What you wrote will almost work, you just want to add the name and date to the GROUP BY clause. Something like this should do.
DELETE FROM chart
WHERE id NOT IN (
SELECT MIN(id)
FROM chart
GROUP BY name, value, date)
The DELETE FROM says you want to be deleting rows from a table. The WHERE clause says which rows you actually want to delete (missing it out will remove everything). The sub-query in the brackets will look through every combination of name, value and date and give you one id back from each combination. Putting it all together, the DELETE should now drop every row whose id isn't the smallest for each group.
Hope that helps!

Related

Assiging a variable in MYSQL based on row number

I'm new to SQL so idk if this is possible, but I'm having some trouble with trying to sort a SQL. What I'm trying to doing is sorting the lastName and firstName of each member then assign there Num based on which row they would be in. I know how to sort the lastName and firstName but I'm not sure how to change the value of the Num. The photo album link shows what I'm trying to do starting from the bottom picture and going up. Thanks!
select first_name, last_name, row_number() over(order by last_name, first_name desc) as Num
from table_name;
According to your requirement arrange the sorting columns and sorting order.
This question is a bit vague, but if I understand you correctly, it looks like you need a simple UPDATE statement.
UPDATE [tablename]
SET Num = #;
This will change the value of Num in each row to the value listed under #. (Assuming # is actually a column and not just part of how the data is displayed. If # isn't a column, I would suggest adding a column for a primary key.)
EDIT : This is not the solution. See comments for more info.

Adding database entries together

I am making a site which allows admins to basically add points for a user.
At this point in time, I have a table, where id_child is unique, and id_points changes. So a constant stream of id_points can come in, however, it will only show the latest id_points, not the total.
I am wondering how I could go about creating a PHP script that could add all of those together.
From the image, the idea is that I want all id_points values added together to give a total, and this is for the same id_child
Use SQL sum() funciton:
select sum(id_points) from table `table_name` where `id_child` = 1
Hope i understood right.
First if you want to show only the latest points added you have to create another table #__points where you will keep every new change of points.
You need 3 columns id as PRIMARY and AUTO_INCRENMENT , pts and user_id . user_id will be FK to id_child.
So when you want to add a new record :
INSERT INTO `#__points` (pts,user_id) VALUES ("$pts",$id)
When you want to select last inserted value for each admin :
SELECT * from `#__points` where user_id=$id ORDER BY id ASC LIMIT 1

How to retrieve count values as multiple columns using group by in single query in MySQL?

I am writing a complex MySQL query. My actual query is more complex than I mentioned below.
I have a table named example and columns are id, name, option_1, option_2 . Of course id column is PK . I want to retrieve like this:
SELECT `id`,`name`,count(`option_1`),count(`option_2`)
My problem is I want to use "GROUP BY `id`" for count(`option_1`) and "GROUP BY `name`" for count(`option_2`) respectively. Now I have to break down it into multiple code in my php code.
How can I achieve what I want in a single query?
What you're asking for doesn't make a ton of sense. You want option 1 grouped by id and option 2 grouped by name, and you want to show all four columns in one result set.
First of all, if id is a primary key, then the count will just be the number of rows in the table since there will be no duplicate ids.
Second, even if id wasn't a primary key, and there were duplicate values, the grouping is different, so the counts represented in your result set would be grouped incorrectly.
Given that id is a primary key, perhaps your intention is actually to get a total count of the rows in the table. Perhaps this query would suit your needs?
SELECT
name,
COUNT(option_2) AS options
FROM
example
GROUP BY
name
UNION ALL
SELECT
'Total' AS name,
COUNT(*) AS options
FROM
example
This should get you a count of all the option_2 values, grouped by name, with the final row having a name of 'Total' and the count being the total number of rows in the table.
Aside from that, I'm not sure you're going to find the answer you're looking for due to the problems you would encounter matching up groupings.

Adding a Row into an alphabetically ordered SQL table

I have a SQL table with two columns:
'id' int Auto_Increment
instancename varchar
The current 114 rows are ordered alphabetically after instancename.
Now i want to insert a new row that fits into the order.
So say it starts with a 'B', it would be at around id 14 and therefore had to 'push down' all of the rows after id 14. How do i do this?
An SQL table is not inherently ordered! (It is just a set.) You would simply add the new row and view it using something like:
select instancename
from thetable
order by instancename;
I think you're going about this the wrong way. IDs shouldn't be changed. If you have tables that reference these IDs as foreign keys then the DBMS wouldn't let you change them, anyway.
Instead, if you need results from a specific query to be ordered alphabetically, tell SQL to order it for you:
SELECT * FROM table ORDER BY instancename
As an aside, sometimes you want something that can seemingly be a key (read- needs to be unique for each row) but does have to change from time to time (such as something like a SKU in a product table). This should not be the primary key for the same reason (there are undoubtedly other tables that may refer to these entries, each of which would also need to be updated).
Keeping this information distinct will help keep you and everyone else working on the project from going insane.
Try using an over and joining to self.
Update thetable
Set ID = r.ID
From thetable c Join
( Select instancename, Row_Number() Over(Order By instancename) As ID
From CollectionStatus) r On c.instancename= r.instancename
This should update the id column to the ordered number. You may have to disable it's identity first.

Retrieving the most recent entry in a database table with a certain value

I have a table with three fields - userID, couponID, last_couponID.
When the user accesses a coupon, I run this query:
mysql_query("INSERT INTO users_coupons (userID, couponID) VALUES ('$recordUserID', '$recordCoupID')");
Further, I have another query that should insert the last couponID into the field last_couponID, by polling the database table and finding the most recent result for the current userID.
I believe it is as such:
SELECT couponID FROM users_coupons ORDER BY userID LIMIT 1
Am I correct? Or should I use a different query?
Like this:
userID couponID
1 3
1 13
1 23
2 5
2 3
So if I wanted userID 2's latest coupon, it'd be '3', and for userID 1, it'd be '23'. I just want the last entry in the database table where the userID matches a value I provide.
I would just add a primary key (autoincrementing) to the users_coupons table.
When you want the latest coupon of a user,SELECT couponID FROM users_coupons WHERE userID = ? ORDER BY id DESC LIMIT 1
Assuming that couponID is numeric, and the last couponID for a certain userId is the greatest (as a number), you can do:
SELECT MAX(couponID) AS lastCouponId FROM users_coupons WHERE userId = <put here the user id>
EDIT: since you've edited your question, I edit my answer.
You have to add an auto-increment primary key, otherwise you can't know exactly which entry is the last one. When I answered, I supposed the last coupon for a certain userId was the one with the greatest couponId. Are you sure you can't just make things work this way?
Something along the lines of...
SELECT couponID
FROM users_coupons
WHERE userID = <current user id>
ORDER BY <primary key of user_coupons table if it's an identity column> DESC
LIMIT 1
...is more appropriate. Your query as it stands doesn't do anything with the 'current' user ID.
If you are actually after the highest couponID then SELECT MAX(couponID)... as suggested by Giacomo is a good idea - coupled with a check for the UserID matching the current user ID.
#Giacomo's answer is valid if you are incrementing the CouponID reliably as an identifier. If you have merged in data or are adjusting this value any other way then it may not be correct.
In theory, if you consider CouponID to be a surrogate key then you cannot use it to explicitly determine insert order. If you intend for it to be used for the purpose of insert order then you also need to make sure your supporting code and DB maintenance plans promote this use.
I contend that the "correct" method is to also store a DateTime

Categories