Check a table against another table SQL - sql

So I have a list of people that I got from table 1.
SELECT UA.user FROM UserAcct UA
I have another table that I need to check against to make sure that the user is not listed in table 2.
LEFT OUTER JOIN AccountsLog AL ON AL.user = UA.user
Ultimately what I am trying to do is make sure that people from table 1 have performed an action on table 2, otherwise their name will be returned. Performing this action will cause their name to show up in table 2. Any help here is greatly appreciated. I am happy to try and elaborate further if this isn't enough information. Thanks!

when you do a left outer join to find records in TABLE A that are not in table B, simply look for NULLs.
So when you LEFT OUTER JOIN the tables on ON AL.user = UA.user, you can then find the missing records with the clause:
WHERE AL.user IS NULL

So if I understand correctly you want Anything from User that not exists in AccountsLog, I think you're on the right track
SELECT UA.user FROM UserAcct UA
LEFT OUTER JOIN AccountsLog AL ON UA.user = AL.user
WHER AL.User is null -- this will give you anything that is on user and not in accountslog
Regards

If your version of SQL supports it, try using Not Exists. Subqueries with NOT EXISTS. I've found it is faster than "left outer joins and filtering for null values".

This will give the users only on UA and not on AL
SELECT UA.user FROM UserAcct UA
MINUS
SELECT AL.user FROM AccountsLog AL
Edit:- For SQL server use EXCEPT instead of MINUS (Supported by Oracle)

Related

Is it possible to detect where the join fails on a certain record?

Please bear with me as this may be a question without a possible answer, but I hope I describe it correctly..
I have a query which joins a number of tables and produces results, and here is the SQL:
SELECT
dbo.Property.PropertyPK,
dbo.Tenancy.TenancyPK,
dbo.Tenant.ContactFK,
dbo.Contacts.strTitle,
dbo.Contacts.strFirstName,
dbo.Contacts.strSurname
FROM dbo.Property
INNER JOIN dbo.Tenancy ON dbo.Property.PropertyPK = dbo.Tenancy.PropertyFK
INNER JOIN dbo.Tenant ON dbo.Tenancy.TenancyPK = dbo.Tenant.TenancyFK
INNER JOIN dbo.Contacts ON dbo.Tenant.ContactFK = dbo.Contacts.ContactPK
The main table is the Property table and I filter out one row by specifying a PropertyPK in my criteria..
My question is.. If the Tenant or Contact record does not exist and I run my query in SQL Management Studio of course I get a message saying there are no rows but can I determine at what stage the join has failed between two tables?
I can of course check this in management studio but I am trying to help the user on the application side to inform them of why there are no rows. My application is in VB and I will write that check if there are no rows and I cannot determine it in SQL..
Sorry for the question in advance..
Derek.. :)
Simply use a LEFT JOIN:
SELECT p.PropertyPK, ty.TenancyPK, t.ContactFK,
c.strTitle, c.strFirstName, c.strSurname
FROM dbo.Property p LEFT JOIN
dbo.Tenancy ty
ON p.PropertyPK = ty.PropertyFK LEFT JOIN
dbo.Tenant t
ON ty.TenancyPK = t.TenancyFK LEFT JOIN
dbo.Contacts c
ON t.ContactFK = c.ContactPK;
This will keep all rows in the Property table. You can then see which primary keys are NULL to see if there were matches in the other tables.
Note that the query is much easier to write and to read when you use table aliases.

SQLite query select all records that does not exist in another table

I am having some problem when trying to perform a SQLite query to get the records which does not exist from another table. Basically I have two database tables:
My exercise table stored all the exercises available whereas the bookedExercise table store the exercises booked by each users. What I am trying to do is, for example if the exercise does exist in the bookedExercise, it should be filtered out.
Here is the SQLite query which I used:
SELECT exercise.exerciseID, exercise.exerciseType, exercise.amout FROM exercise LEFT JOIN bookedExercise WHERE exercise.exerciseID = bookedExercise.exerciseID AND bookedExercise.exerciseID IS NULL
However, it returned me empty records. Any ideas?
Thanks in advance.
If you're fine with not using joins you could use
SELECT * FROM exercise WHERE exerciseID not in (SELECT exerciseID FROM bookedExercise)
When you are using LEFT JOIN, you must put the join condition into the ON clause:
SELECT exercise.exerciseID,
exercise.exerciseType,
exercise.amout
FROM exercise /* !! */
LEFT JOIN bookedExercise ON exercise.exerciseID = bookedExercise.exerciseID
WHERE bookedExercise.exerciseID IS NULL
Your SQL looked okay... I think the problem might be you have a datatype mismatch. You have exercise ID as an integer in one table and text in another.
Also, if you have huge data volumes, you may want to consider an anti-join:
select
e.*
from
exercise e
where not exists (
select 1
from bookedExercise be
where
e.excerciseId = be.exerciseID
)
-- edit --
On second glance, your SQL was not okay. You had your join condition in the where clause. This little change would fix your existing SQL:
SELECT exercise.excerciseId , exercise.exerciseType , exercise.amout
FROM exercise LEFT JOIN bookedExercise on
exercise.excerciseId = bookedExercise.exerciseID
WHERE bookedExercise.exerciseID IS NULL

How to Select Specific data on query with RIGHT JOIN statement?

I am joining 2 tables using RIGHT JOIN statement. I used below query and it works good. However it still display all data whenever I tried to select specific user
SELECT TBLNOTIFICATIONS.NOTIFICATION_ID, TBLNOTIFICATIONS.NOTIFICATION_TYPE, FILENAMES_LIST.LOCATION_FILENAME, TBLNOTIFICATIONS.NOTIFICATION_DATE
FROM TBLNOTIFICATIONS
RIGHT JOIN FILENAMES_LIST
ON TBLNOTIFICATIONS.NOTIFICATION_ID=FILENAMES_LIST.NOTIFICATION_ID
WHERE TBLNOTIFICATIONS.USER_ID='JCON'
What should I do to select data from specific user?
Thanks in advance.
You are filtering on the left table, so all the data of the right table will still be shown.
It is probably enough to change the query to a LEFT JOIN to get the results you want.
Besides that, you can use aliases to make your query more readable, like so:
SELECT tn.NOTIFICATION_ID, tn.NOTIFICATION_TYPE, fl.LOCATION_FILENAME, tn.NOTIFICATION_DATE
FROM TBLNOTIFICATIONS AS tn
LEFT JOIN FILENAMES_LIST AS fl
ON tn.NOTIFICATION_ID = fl.NOTIFICATION_ID
WHERE tn.USER_ID='JCON'

Inner join or something else?

I'm trying to get 2 results into 1 html table, the results of a user being kicked/banned. A UUID is a unique code for every user.
The UUID is stored in BAT_players.
The player name is also stored in BAT_players
There are 3 table's: BAT_players, BAT_ban and BAT_kick
I'm trying to get the history of a user in a html table, this includes kicks and bans. Right now there are only bans in this history, i'm trying to add kicks too. This query is working fine, it shows only bans though.
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players
INNER JOIN BAT_ban
ON BAT_ban.UUID=BAT_players.UUID
Unfortunately it is not working with this query, it's giving me an empty history. What am i doing wrong with the second inner join?
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players
INNER JOIN BAT_ban
ON BAT_ban.UUID=BAT_players.UUID
INNER JOIN BAT_kick
ON BAT_kick.UUID=BAT_players.UUID ORDER BY ban_id DESC
;
Thanks!
The problem is that a "null" on any of your inner joins will eliminate that row from the result set.
One solution (perhaps the best solution) is to use left joins.
Another is to take the UNION of two inner joins.
Here's a great link to help visualize INNER, OUTER, LEFT and RIGHT joins:
http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
Try using LEFT JOIN:
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players LEFT JOIN
BAT_ban ON BAT_ban.UUID=BAT_players.UUID LEFT JOIN
BAT_kick ON BAT_kick.UUID=BAT_players.UUID
ORDER BY ban_id DESC
To replace NULL values with empty strings (for SQL Server):
SELECT ISNULL(BAT_ban.ban_staff,''), ISNULL(BAT_ban.ban_state,''), ISNULL(BAT_ban.ban_server,''), ISNULL(BAT_ban.ban_begin,''), ISNULL(BAT_ban.ban_end,''), ISNULL(BAT_ban.ban_id,''), ISNULL(BAT_kick.kick_id,''), ISNULL(BAT_ban.ban_reason,''), BAT_players.BAT_player, ban_soort
FROM BAT_players LEFT JOIN
BAT_ban ON BAT_ban.UUID=BAT_players.UUID LEFT JOIN
BAT_kick ON BAT_kick.UUID=BAT_players.UUID
ORDER BY ban_id DESC
For MySQL, replace ISNULL with IFNULL.
An INNER JOIN requires a value in both tables, so if you use it for both kicks and bans, you will only see users who have been both kicked and banned.
To show users who have been either kicked or banned, you need to change both joins to LEFT JOIN, which essentially means "join if you can, but don't discard rows if you can't". That will include users who have been neither kicked nor banned, so you will also want an extra condition in the WHERE clause saying BAT_ban.ban_id IS NOT NULL OR BAT_kick.kick_id IS NOT NULL.
Note that where a user has multiple bans and multiple kicks, this will produce a row for every combination of ban and kick, since there is no rule to determine which ban should line up with which kick.
An alternative is to write two queries, each using INNER JOIN, and then combine the results. If you give them the same number and type of output columns (leaving NULL for those which aren't applicable) you can use UNION to run both and return the complete result set in one go.

SQL / Access - Left Join question, where do the values come from?

I have a cross tab query that looks like this:
State Building 1 2 3 4 5
NY
SC
FL
The problem I am having is that I want all of the states to show up, regardless of whether or not there is data. So, I need a Left Join. Unfortunately, when I substitute the Inner Join for Left Join in the code, nothing changes. I am just trying to figure out where the problem is coming from, and I think it may be one of the following causes:
The query doesn't know where to pull
the values from (The states are all
listed in a look up but this may
not be where it's looking)
Left Joins don't work on cross tab
queries.
Could someone please tell me what I am doing wrong?
Here's the SQL:
TRANSFORM Nz(Count(Demographics.ID))+0 AS CountOfID
SELECT Demographics.State
FROM Research
INNER JOIN ( Demographics
INNER JOIN [Status]
ON Demographics.ID=[Status].ID
)
ON (Research.ID=Demographics.ID)
AND (Research.ID=[Status].ID)
WHERE ((([Status].Building_Status)='Complete'))
GROUP BY Demographics.State,
[Status].Building_Status
PIVOT Research.Site In (1,2,3,4,5,6,7,8,9,10,11)
Ideally, I could specify the row values in the In statement above (which is currently specifying column values 1-10), but I don't think this can be done.
I didn't completely get your example, but from your comment "I want all of the states to show up, regardless of whether or not there is data", I think you want an "OUTER" join. Outer joins do just that -- they include data regardless of whether or not there is a "match". Inner joins (the default) include data only if there is a match.
Hope this helps,
John
You should change it this way:
TRANSFORM Nz(Count(Demographics.ID))+0 AS CountOfID
SELECT Demographics.State
FROM Demographics
LEFT JOIN ( Research
LEFT JOIN [Status]
ON Demographics.ID=[Status].ID
)
ON (Research.ID=Demographics.ID)
AND (Research.ID=[Status].ID)
WHERE ((([Status].Building_Status)='Complete'))
GROUP BY Demographics.State,
[Status].Building_Status
PIVOT Research.Site In (1,2,3,4,5,6,7,8,9,10,11)
If your problem is that there may be 0 rows in table Demographics with State = 'NY' (for example) but you want to see state 'NY' in the results anyway, then you need another table e.g. States that has all the states in it, and make this your driving table:
SELECT States.State
FROM States
LEFT OUTER JOIN Demographics ON Demographics.state = States.state
...
you can use a two steps solution (it is more readable)
first enclose your actual (and working) sql statment as a view
create view step1 as
TRANSFORM ....
SELECT ...
FROM ...
PIVOT ...
and then create a select like:
(you will need a state table like #Tony Andrews says)
select * -- or whatever
from state
left join step1 on state.id = step1.state
and that's all