Using Join to parse out duplicate data - sql

I am having a bit of a problem here with this statement below using tables:
[Users] Name,Email,Subscribed
[Email] Name,Email,Subscribed
Basically what needs to be accomplished is all the Subscribed Users in the Users table need to be checked against the users in the Email table to see if they exist in the table or not, and only return the users in the Users table which are not found in the Email table.
Here is the statement I've used, but it returns millions of rows and takes forever, and it is returning every email address in the Email table, I don't think this is the best way to approach this issue because it is not returning accurate data. Any thoughts?
SELECT Distinct c.Name,c.Email from Users c
INNER JOIN Email e on c.Email <> e.Email
WHERE c.Subscribed=1

I think this is what you are looking for.
SELECT c.Name,c.Email
FROM Users c LEFT JOIN Email e ON (c.email=e.email)
WHERE (e.email is null) and (c.subscribed=1)
The INNER JOIN in your query with no ON clause is why you are getting wacky results.

change the <> to =
You are doing an join on non-equality so that is why your result size is exploding.
On a side note - check into foreign keys going forward - they make this type of cross table referential integrity a non-issue.
UPDATE - if you want results in one table that are not in the other do:
select * from table1 where email not in (select distinct email from table2);
This will give you all the records in table1 that don't match an email in table 2.
HTH

You will want to use a LEFT JOIN to accomplish this:
SELECT Distinct u.Name, u.Email
FROM Users AS u
LEFT JOIN Email AS e ON u.Email = e.Email
WHERE e.Email IS NULL
AND u.Subscribed = 1
Graphical explanation of JOINS may be helpful
I strongly recommend using Foreign Keys to maintain referential integrity.

Related

trouble with inner joining 2 tables

I have a database with 2 tables in it one is 'enlistments' and the other one is 'users'. In the enlistments table I have a user_id and in the users table I have a name. I want to get the name of the user which belongs to the id.
I know I need to do this with an inner join like this:
SELECT enlistments.round_id, users.name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.name
WHERE enlistments.activity_id = 1;
However I get this error: Warning: #1292 Truncated incorrect DOUBLE value
I did some research and found out it has to do with comparing an int with a string but I don't know how to solve the problem.
This is how my database looks like
join on is the condition you use to join the tables. Here it's enlistments.user_id=users.id.
select e.round_id
,u.name
from enlistments e join users u on u.id = e.user_id
where activity_id = 1
round_id
name
1
test2
Fiddle
To validate and be sure you are pulling back the exact data desired, I usually provide aliases for each column brought back and make sure to bring back the join columns also. It's good practice to label where the columns returned originated.
SELECT
Enlistments.UserID as Enlistments_UserID,
Users.ID as Users_ID,
enlistments.round_id as Enlistments_RoundID,
users.name as Users_Name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.id
WHERE enlistments.activity_id = 1;
SELECT EN.round_id, US.name
FROM enlistments EN
INNER JOIN users US
ON US.name= CAST(EN.user_id AS VARCHAR)
WHERE EN.activity_id = 1
What you are needing is the function cast that can convert any kind of data into another, so you'll pass your integer value as the first argument followed by "AS '%DATATYPE'" where %DATATYPE is the kind of data you want to achieve.
In your case:
SELECT CAST(123456 AS VARCHAR)
-- RETURNS : '123456'
Anyway, I’m not sure that you can be able to join these two tables with the join you are using.
For more help please share some data.

How to select records from database table which has to user id (created_by_user, given_to_user) and replace users id by usernames?

This is task table:
This is user table:
I want to select user tasks.
I would give from backend ("given_to_user) id.
But The thing is I want that SELECTED data would have usernames instead of Id which is (created_by_user and given_to_user).
SELECTED table would look like this.
Example:
How to achieve what I want?
Or maybe I designed poorly my tables that It is difficult to select data I need? :)
task table has to id values that are foreign keys to user table.
I tried many thinks but couldn't get desired result.
You did not design poorly the tables.
In fact this is common practice to store the ids that reference columns in other tables. You just need to learn to implement joins:
SELECT
task.id, task.title, task.information, user.usename AS created_by, user2.usename AS given_to
FROM
(task INNER JOIN user ON task.created_by_user = user.id)
INNER JOIN user AS user2 ON task.created_by_user = user2.id;
Do you just want two joins?
select t.*, uc.username as created_by_username,
ug.username as given_to_username
from task t left join
users uc
on t.created_by_user = uc.id left join
users ug
on t.given_to_user = ug.id;
This uses left join in case one of the user ids is missing.

SQL SELECT * FROM 2 tables

I am building a small database app for friends where table 1 is contacts and table 2 is users. I can find email on both (One as the loggued in user and the other as the owner of the contact)
SELECT *
FROM contacts
WHERE contacts.username = users.email
I try to show all contacts fields where username is equal to already loggued in users (email)
Thanks you very much!
It sounds like you're trying to JOIN two tables together. Ideally, you don't want to use the email as the primary key on a table (the smaller the data, the faster your JOIN will be); a better option would be to add an auto-incrementing Id (integer) to both the Contacts and Users tables, set as the primary key (unique identifier). Joining on integers is much faster, as integers are 4 bytes per row, vs string which (in MySQL) is 1 per character length (latin1 encoding) + 1 byte.
Anyway, back to the original question. I believe the query you're looking for (MySQL syntax) is:
SELECT c.Id, c.Col1, u.Col2, ...
FROM contacts AS c
INNER JOIN users AS u ON u.email = c.username
Additionally, I would avoid the use of *, as it slows down the query a bit. Instead, try to specify the exact columns you need.
Try the following. Also, I would suggest you learn about joins in SQL.
SELECT *
FROM contacts
INNER JOIN
users on contacts.username = users.email
Use Inner Join:
SELECT *
FROM contacts as c
INNER JOIN
users as u on u.email = c.username

Query two joins on the same value and table

I'm having trouble doing the following query. The idea is that I have two tables Stores and Users. In Stores I have the columns store_owners and store_last_modified, both values are integer that are related to the id of dbo.Users. How I can display the name that is stored in users related to the two columns. Like that:
select stores.name , users.name as name_store_owner , users.name as name_store_last_modified
from stores
LEFT JOIN users ON stores.store_owners=users.id (related to name_store_owner)
LEFT JOIN users ON stores.store_last_modified=users.id (related to name_store_last_modified)
How do I do that?
Thank you in advance.
You need to give the tables aliases, so you can refer to the same table twice in the from clause. In addition, you need to refer to the right table (users not stores):
select s.name, uo.name as name_store_owner, um.name as name_store_last_modified
from stores s left join
users uo
on s.store_owners = uo.id left join
users um
on s.store_last_modified = um.id
It appears that the condition can be checked without referring the table twice.
select * from
stores s
left join
users u on u.id = s.store_owners
and u.id = s.store_last_modified
From your question it appears that user id (id) should match with both the columns in the stores table for a single row.

Oracle SELECT WHERE value exists or doesn't exist

I have 3 tables; CASES, USERS and USER_META. For this issue you need to know that the USER_META table has 3 columns; user_id, meta_key and meta_value
Each user is associated with many CASES and each USER is associated with many USER_META
My current query is like this
SELECT CASES.*, USERS.*, USER_META.*
FROM CASES
JOIN USERS ON USERS."user_id" = CASES."user_id"
JOIN USER_META ON USER_META_"user_id" = USERS."user_id"
The problem with this approach is that each USER has A LOT of USER_META so my result set has too many rows. How can I rewrite this query so that I can select only the USER_META where the USER_META."meta_key" is equal to a certain value yet still get the result if they do not have this USER_META."meta_key" set yet
For example:
SELECT CASES.*, USERS.*, USER_META.*
FROM CASES
JOIN USERS ON USERS."user_id" = CASES."user_id"
JOIN USER_META ON USER_META_"user_id" = USERS."user_id"
WHERE USER_META."meta_key" = 'my_key'
This would work great but not all users have a value of "my_key" in the "meta_key" column and we still need to view their CASE. For users that do not have the "meta_key" the result should just return the CASE and USER columns.
How can I rewrite this query so it gets the result for both users with this meta_key and without?
Thanks, I hope this makes sense.
I would use a LEFT JOIN
SELECT CASES.*, USERS.*, USER_META.*
FROM CASES
JOIN USERS ON USERS."user_id" = CASES."user_id"
LEFT JOIN USER_META ON USER_META."user_id" = USERS."user_id" AND USER_META."meta_key" = ?
you need to use OUTER JOIN with the table that may have no results. In Oracle, use (+) near to the field name of the join sentence with this table. This link may help you: http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm