I know there is a lot of results that come up when you search this, but I can't find a simple, clear answer to what I am trying to to.
To make it simple, say I have a table with two columns:
'call_id' (pk, unique, auto increment) & 'guid'
I want to delete any rows with a duplicate guid, keeping just the first occurrence of each guid.
You can use join:
delete c
from calls c left join
(select guid, min(call_id) as minci
from calls
group by guid
) cc
on cc.minci = c.call_id
where cc.minci is null;
Related
I've tried searching an answer for this and I can't realy find the one that fits what I'm looking for.
I'm making a small web application that allows an admin to create course material and a test, that a user will be assigned.
What I am trying to figure out, is how a user, who has been assigned a course, can access that course by clicking a button.
I have created one table which stores the user information, with a user ID being a primary key. I have a course table, which stores all materials and the course's test, with a course id being that table's primary key.
I made a third table which is an assigned_courses table, it contains two foreign keys. One referencing the user id from the user table, and one referencing the course id on the course table.
I've inserted a few images to show what you mean.
I can't quite figure out the Sql syntax to pull course materials and test based on the assigned_course table.
All feedback appreciated. This is the two foreign keys that reference the user id (id) and the course id(u_id)
Not sure what column names you have so I used * instead. You can use JOIN (AKA INNER JOIN) to link the tables together. You join on the primary keys of the 2 tables.
I have created one table which stores the user information, with a
user ID being a primary key. I have a course table, which stores all
materials and the course's test, with a course id being that table's
primary key.
I used id for your user table and course_id for the course table. Change as needed.
Find all courses for a given user.
SELECT a.*
FROM course a
JOIN assigned_course b ON a.course_id = b.id
WHERE b.u_id = :userId
;
Find all users for a given course.
SELECT a.*
FROM user a
JOIN assigned_course b ON a.id = b.u_id
WHERE b.id = :courseId
;
EDIT #1 - Subquery without JOIN
Thanks for your feedback, as I stated above, I was hoping to avoid a
join.
I highly recommend you learn joins. They are essential when you need to query more than 1 table. In this case, you can use a sub-query to find matching courses for a user but you won't be able to access that user data at the same time; that is the power of a join. I'll include a final example underneath showing how to get courses and user data at the same time.
Find all courses for a given user (using sub-query)
SELECT a.*
FROM course a
WHERE course_id IN (
SELECT id
FROM assigned_course b
WHERE u_id = :userId)
;
Final example showing courses related to users (many-to-many)
SELECT * -- You now have access to a, b, and c data
FROM course a
JOIN assigned_course b ON a.course_id = b.id -- joined by PKs
JOIN user c ON c.id = b.u_id -- joined by PKs
WHERE c.id = :userId
;
It sounds to me like you want to use SQL Join syntax which goes as follows:
select column1, column2, column3 etc...
from table1
join course on table1.id = course.id
join assigned_course on table1.id = assigned_course.id
replace the column1,2,3 etc with the actual column names, and replace the foreign_key_name with the actual name of the foreign key in the sub-table and the same for the user_primary_key
you can find some other examples of mysql joins here
as far as how to implement them into your html or php file, that is a very different question and would require knowing alot more about how your code is setup in the form
a place that is pretty user friendly is that might help with pulling the data is here just make sure you are aware of using prepared statements for your code
I have a table 'Directors' and another table 'company_directors'.
In the directors table there are duplicate records with the same "fullname", I want to select just the one with the longest "address".
and I want to update the foreign key "directorID" in the 'company_directors' table.
I have tried to use GROUP BY but i have no way of specifying which of the duplicates I want to keep... I also do not know how to go about updating the foreign key records to reflect the selected 'director_id' of the duplicates.
Update:
I have been able to flag the duplicate records as inactive by altering the 'directors' table and adding an 'active' column. However I still want to correct the references in the 'company_directors' table, before deleting the inactive/duplicate records.
If you want to do this in-place, then update the second table first.
update company_directors cd join
directors d
on cd.DirectorId = d.DirectorId join
(select fullname,
substring_index(group_concat(directorId order by length(Address) desc), ',', 1) as newDirectorId
from directors
group by fullname
) dnew
on d.fullname = dnew.fullname
set cd.DirectorId = dnew.newDirectorId
where dnew.newDirectorId = d.DirectorId;
Then, update directors by deleting the uninteresting directors:
delete cd
from directors d left join
cd.DirectorId = d.DirectorId join
(select fullname,
substring_index(group_concat(directorId order by length(Address) desc), ',', 1) as newDirectorId
from directors
group by fullname
) dnew
on d.fullname = dnew.fullname and d.directorId = dnew.newDirectorId
where dnew.newDirectorId is null;
I'm not thrilled with this approach, because newDirectorId (in both queries) ends up being a string rather than a number. But, MySQL doesn't support window functions, so this is possibly the simplest approach.
That said, I would encourage you to take a slightly different approach. First, backup the tables before you do anything.
Then, instead of deleting from directors, add a flag indicating whether the record is active. Then, inactive the records with shorter addresses. Investigate the results to be sure they are what you want. Manually change the flag where it is not correct. Then, go back to the company_directors table and fix the records that point to inactive records.
Question - let's say I have 2 tables.
Table 1 - name is permission_list, columns are ID (unique ID), col_ID, user_ID
Table 2 - name is list_entries, Columns are ID (unique ID), title, description, status
I want to select all the rows from table 2 that have status of 'public' as well as all the rows from table 2 that the ID from table 2 shows up in table 1 (under the column col_ID) AND if the user_ID in table 1 matches a certain value. So, anything public, or anything that this specific user has listed under the permissions table. This query would also remove duplicates - in case the user gets a public entry listed in their permissions_list, it wouldn't show up twice.
Hope that makes sense!
Here you go:
SELECT DISTINCT table2.* from table2
LEFT JOIN table1 USING (id)
WHERE status='public'
OR user_ID='someuser';
You need to get some education on JOIN for your first thing, and the second thing is called DISTINCT.
Start here... https://www.google.com/
You have not specified your join condition so we can't give you code samples really. Also the way you worded your question, I'm not entirely sure you don't want a UNION. Read up on those concepts and come back here when you can improve the question.
SELECT table_2.status, table_2.ID, table_1.col_ID
FROM table_1 JOIN table_2
WHERE table_2.status = 'public'
AND table_2.ID = table_1.col_ID
AND table_1.user_ID = 'certain value'
;
Try this
I'm trying to optimize this query but I can't seem to get it. Any help is more than welcomed. This is inside a stored procedure, so the 1 is replaced by an IN parameter.
Table userGroupRelation
userGroupID BIGINT --> foreign key to userGroupID in groups table
userID BIGINT --> foreign key to the users table
Table folders
ownerID BIGINT --> foreign key to the users table
postersGroup BIGINT --> foreign key to userGroupID in groups table
other stuff ...
SELECT folders.*,COUNT(userGroupRelation.userID) AS users
FROM folders
LEFT JOIN userGroupRelation
ON folders.postingGroupID = userGroupRelation.userGroupID
WHERE folders.ownerID = 1
OR userGroupRelation.userGroupID IN (
SELECT userGroupID FROM userGroupRelation WHERE userID = 1)
GROUP BY folders.folderID;
I basically want to get all the folders a user can see (either because he owns it or because he is in a group of posters for that folder)
I suggest two approaches. One is similar to your own, but removing the subquery and correcting the COUNT clause. I should mention it is unclear from your question whether the COUNT ... AS users result is of importance here, since you only specified you want to get all folders for a user.
SELECT
folders.*,
COUNT(DISTINCT IFNULL(userGroupRelation.userID, folders.ownerID)) AS users
FROM
folders
LEFT JOIN userGroupRelation ON folders.postingGroupID = userGroupRelation.userGroupID
WHERE
folders.ownerID = 1
OR userGroupRelation.userID = 1
GROUP BY
folders.folderID
;
This is somewhat better than your own solution because the subquery is eliminated, but it still leaves with this OR condition which is difficult to optimize -- it works on two different tables.
Edit: this next solution neither answers the question nor does it work at all :(
A completely different approach is to start with the users table (assuming you have one, of course):
SELECT
folders.*
FROM
users
LEFT JOIN folders ON (folders.ownerID = users.id)
LEFT JOIN userGroupRelation ON (userGroupRelation.userId = users.id)
LEFT JOIN folders ON (folders.postingGroupID = userGroupRelation.userGroupID)
WHERE
users.id = 1
GROUP BY
folders.folderID
;
This one is far better optimized if you have proper indexes on users.id and all joining columns. However:
It will not tell you the amount of (other) users per folder
SELECT filders.* .... GROUP BY filders.folderId is not strictly valid SQL -- though it will work if you're not using strict sql_mode. From you own query I can see you're not, so I won't dwell into that.
the code below provide a result too much Infact i want to list the customer that never buy somethink How can i fix the code below
SELECT
webboard.listweb.id,
webboard.listweb.iditempro,
webboard.listweb.url,
webboard.listweb.useradddate,
webboard.listweb.expiredate,
webboard.prorecord.urlpostonweb
webboard.prorecord.urlpostonweb
FROM
webboard.listweb ,
webboard.prorecord
Where listweb.id Not In
(select webboard.prorecord.idlist From webboard.prorecord )
Using the syntax
FROM
webboard.listweb ,
webboard.prorecord
will perform a cartesian, or cross, join on the tables involved. So for every row in the table listweb all the rows in prorecord are displayed.
You need to use an INNER JOIN to only select the rows in listweb that have related rows in the prorecord table. What are the fields which identify the rows (your Primary Keys) and what is the name of the foreign key field in the prorecord table?
EDIT: Just re-read the question and comments and I see you want the rows in listweb which do not have an entry in prorecord
Your SELECT will then look like:
SELECT
webboard.listweb.id,
webboard.listweb.iditempro,
webboard.listweb.url,
webboard.listweb.useradddate,
webboard.listweb.expiredate,
webboard.prorecord.urlpostonweb
-- webboard.prorecord.urlpostonweb -- You have this field twice
FROM webboard.listweb LEFT JOIN webboard.prorecord
ON webboard.listweb.id = webboard.prorecord.idlist -- I'm guessing at the foreign key here
WHERE webboard.prorecord.idlist IS NULL