Alright, so I understand how to do a mysql query to return results based on one search parameter. But I have a table that contains usernames and data. The data should be unique to each username, but I want to return any instances where that data might overlap over multiple usernames. An example would be
Username | Data Field
----------------------------------------------
Test | Abcd1234
Test2 | efgh5678
Test3 | Abcd1234
Test4 | efgh5678
I want my php script to return all instances where duplicate entries are found in the data field. Note that, neither the data field nor username field are unique in this table. The table gets populated whenever the user completes an action, so there should be many entries for each username, but each time they should have the same data field. I only want to check when two different usernames have the same data field. Does anyone have any idea how this can be done in php or a mysql select statement? It may take more than one query and that is okay. I've tried searching on how to find duplicate emails based on usernames, but the results I found were more on preventing duplicate registrations in the first place.
Basically, you want to count the number of unique users for each data field. This is an aggregation query:
select data, count(distinct username) as numusers
from table t
group by data;
You should be able to get the unique user names with this query:
select data, count(distinct username) as numusers,
group_concat(distinct username) as users
from table t
group by data
having count(distinct username) > 1;
This will create a comma separated list of users "using" the same data.
Related
Is it possible to store an array of ID's within a table column which reference ID's from another table so that I can do a select query and determine whether a specific ID is within that column?
Example scenario below.
I have 3 tables like this:
Table: tab_groups with Columns: id, name
Table: tab_users with Columns: id, name, groups
Table: tab_forums with Columns: id, title, req_groups
A user can belong to multiple groups, the ID's of the groups that they belong to are stored in the groups column.
A forum can have multiple required groups specified, which the ID's of are stored in req_groups. A user must belong to at least 1 group which matches with at least 1 required group in order to view the forum.
How should I store the groups and req_groups columns so that I can later do a SELECT query to check whether a user belongs to a group which matches with a group ID required to view the forum?
Also how would I update those columns to include new ID's or remove old ones?
Currently I just have a pretty inefficient method which involves storing them as a string with a separator (like 1,2,3,4), then splitting them in PHP and doing a comparison check in a loop.
For updating I just check whether a value exists, and add it onto the string.
I have a web application that stores points in a table, and total points in the user table as below:
User Table
user_id | total_points
Points Table
id | date | user_id | points
Every time a user earns a point, the following steps occur:
1. Enter points value to points table
2. Calculate SUM of the points for that user
3. Update the user table with the new SUM of points (total_points)
The values in the user table might get out of sync with the sum in the points table, and I want to be able to recalculate the SUM of all points for every user once in a while (eg. once a month). I could write a PHP script that could loop through each user in the user table and find the sum for that user and update the total_points, but that would be a lot of SQL queries.
Is there a better(efficient) way of doing what I am trying to do?
Thanks...
A more efficient way to do this would be the following:
User Table
user_id
Points Table
id | date | user_id | points
Total Points View
user_id | total_points
A view is effectively a select statement disguised as a table. The select statement would be: SELECT "user_id", SUM("points") AS "total_points" FROM "Points Table" GROUP BY "user_id". To create a view, execute CREATE VIEW "Total Points View" AS <SELECT STATEMENT> where SELECT STATEMENT is the previous select statement.
Once the view has been created, you can treat it as you would any regular table.
P.S.: I don't know that the quotes are necessary unless your table names actually contain spaces, but it's been a while since I worked with MySQL, so I don't remember it's idiosyncrasies.
You have to user Triggers for this, to make the users total points in sync with the user_points table. Something like:
Create Trigger UpdateUserTotalPoints AFTER INSERT ON points
FOR EACH ROW Begin
UPDATE users u
INNER JOIN
(
SELECT user_id, SUM(points) totalPoints
FROM points
GROUP BY user_id
) p ON u.user_id = p.user_id
SET u.total_points = p.totalPoints;
END;
SQL Fiddle Demo
Note that: As noted by #FireLizzard, if these records in the second table, are frequently updated or delted, you have to have other AFTER UPDATE and AFTER DELETE triggers as well, to keep the two tables in sync. And in this case the solution that #FireLizzard will be better in this case.
If you want it once a month, you can’t deal with just MySQL. You have too « logic » code here, and put too logic in database is not the correct way to go. The trigger of Karan Punamiya could be nice, but it will update the user_table on every insert in points table, and it’s not what you seem to want.
For the fact you want to be able to remove points, just add bsarv new negated rows in points, don’t remove any row (it will break the history trace).
If you really want it periodically, you can run a cron script that does that, or even call your PHP script ;)
I have a DB with several tables that contain basic, static ID-to-name data. 2 Columns only in each of these reference tables.
I then have another table that will be receiving data input by users. Each instance of user input will have it's own row with a timestamp, but the important columns here will contain either one, or several of the ID's related to names in one of the other tables. For the ease of submitting and retrieving this information I opted to input it as text, in json format.
Everything was going great until I realized I'm going to need to Join the big table with the little tables to reference the names to the ID's. I need to return the IDs in the results as well.
An example of what a few rows in this table might look like:
Column 1 | Column 2 | Timestamp
["715835199","91158582","90516801"] | ["11987","11987","22474"] | 2012-08-28 21:18:48
["715835199"] | ["0"] | 2012-08-28 21:22:48
["91158582","90516801"] | ["11987"] | 2012-08-28 21:25:48
There WILL be repeats of the ID#'s input in this table, but not necessarily in the same groupings, hence why I put the ID to name pairings in a separate table.
Is it possible to do a WHERE name='any-of-these-json-values'? Am I best off doing a ghetto join in php after I query the main table to pull the IDs for the names I need to include? Or do I just need to redo the design of the data input table entirely?
First of all:
Never, ever put more than one information into one field, if you want to access them seperately. Never.
That said, I think you will need to create a full N:M relation, which includes a join table: One row in your example table will need to be replaced by 1-N rows in the join table.
A tricky join with string matching will perform acceptably only for a very small number of rows, and the WHERE name='any-of-these-json-values' is impossible in your construct: MySQL doesn't "understand", that this is a JSON array - it sees it as unstructured text. On a join table, this clause comes quite naturally as WHERE somecolumn IN (1234,5678,8012)
Edit
Assuming your Column 1 contains arrays of IDs in table1 and Column 2 carries arrays of IDs in table2 you would have to do something like
CREATE TABLE t1t2join (
t1id INT NOT NULL ,
t2id INT NOT NULL ,
`Timestamp` DATETIME NOT NULL ,
PRIMARY KEY (t1id,t2id,`Timestamp`) ,
KEY (t2id)
)
(you might want to sanity-check the keys)
And on an insert do the following (in pseudo-code)
Remember timestamp
Cycle all permutations of (Column1,Column2) given by user
Create row
So for your third example row, the SQL would be:
SELECT #now:=NOW();
INSERT INTO t1t2join VALUES
(91158582,11987,#now),
(90516801,11987,#now);
I can't figure out why MySQL is returning an empty set for only certain users in the following query. I have the same info entered in every single profile, and only a couple userid's will return a result.
SELECT userinfo.userid, userinfo.location, locations.locationsName, locations.locationsID FROM userinfo
INNER JOIN locations ON locations.locationsID = userinfo.userid
WHERE userinfo.userid = '$userid'
Here are my tables (there are more columns, but they're irrelevant to this search)
userinfo
userid | location
locations
locationsID | locationsName
For example, I can open PHPMyAdmin and type in that query (changing the $userid). I made sure every single username has the same info entered (aside from having a different userid).
Because you're joining the LocationID to the UserID.
Based on your given schema, you probably want to join userinfo.userid = location.userid
How to connect two mysql tables in which I am inserting data in same time?
I have table customers which is my app table, and I have user which is used by library I use for my framework, this library handles users and authorization.
I wanted to have user_id (which is id from user) in customers, but I am creating those two tables in same time.
Any ideas? Thanks!
the php command mysql_insert_id gives you the id of the last record inserted into a table. So from my undestanding if your inserting a user you could get the id then insert that into another table?
http://php.net/manual/en/function.mysql-insert-id.php
Or have I understood your question wrongly?
It is simply not possible. Nothing can happen at the same time in a program.
What is possible is to:
Start a database transaction
perform your first query
retrieve the table's key; if it's an autoincrement, there are built-in ways to retrieve the last inserted key in every database API
perform your second query using the retrieved key as a parameter
Commit the transaction; But if an error occurred, you need to rollback the whole transaction
This is how it is done, and it behaves exactly like you want it to.
How about a link table?
users_customers
user_id | customer_id
=====================
1 | 648785552
5 | 145778304
4 | 654566055
You can then join the tables together using this table, for example like this:
SELECT users.name, customers.address
FROM users
JOIN users_customers
ON users_customers.user_id = users.id
JOIN customers
ON users_customers.customer_id = customers.id