Finding records in dba_users not in individual usertable - sql

I have the following problem in Oracle 11g:
I have a table TBL_PERSON listing all users of my application and I need to find out all users of the database that are NOT mentioned in TBL_PERSON.
Count of tbl_person is 4207.
Count of dba_users/all_users is 4244. This means, that the difference of 37 users are system users not using the application.
So far so good. How do I identity the system users?
ID in table INT_PERSON is equal to USER_ID in dba_users. I expect a list of all users from dba_users table not listed in INT_PERSON. (37 rows)
I tried the following:
SELECT *
FROM dba_users
WHERE USER_ID
NOT
IN (SELECT ID
FROM LCM.TBL_INT_PERSON);
The result is 3804 rows, also showing users from INT_PERSON -> not what I expected
Then tried:
SELECT *
FROM dba_users a
WHERE USER_ID
NOT
IN (SELECT ID
FROM LCM.TBL_INT_PERSON b
where b.id = a.User_id);
Which makes no difference.
Those post do not solve my problem:
Find records in one table which does not have a matching coulmn data existing in another table
Select records from a table, which don't exist in another table
Or is it a secret of the dba_users table? Where is my mistake?

How do I identity the system users?
First verify the count of application users.
This query should return all the ID of the application users, i.e. 4207
If not - you have other problem, than you describes.
select USER_ID from dba_users
INTERSECT
select ID from TBL_INT_PERSON;
Now show the system users
select USER_ID from dba_users
MINUS
select ID from TBL_INT_PERSON;
This should return the IDs of the system user.
General note - simple subtraction of count(*) of two tables could be misleading, as there could be duplicated key and nulls in the tables. Using set operation as above is more secure.

Related

SQL Column Comparison

I have two queries I need in one table, and haven't been able to find results in searching.
In the first table there is a UserID, which is a number, along with what the actual user id is and user's name.
My issue is that in every other query the user is only referred to as this number. I'm needing help in how to translate this UserID value into the actual User's name in my other queries.
Table with User's ID and User's Name:
SELECT *
FROM [Table].[dbo].[User]
Table example where the user is only referred to as this number, along with all other tables:
SELECT *
FROM [Table].[LoginStatus]
You need to join the two tables:
SELECT u.[UserName], l.*
FROM [LoginStatus] l
JOIN [Users] u ON u.id = l.user_id

Setting a column value for only one user depending on results

I'm currently playing around with SQL and trying to find the best way to accomplish this:
I currently have a user table that has a user_id, organisation_id, registered_datetime. There are
a number of users in this table with different organisations. There may be 3 different users in
1 organisation, or 1 in 1 organisation, etc.
I have added a new column called admin_user and I am trying to string up an SQL statement together
to update the admin user column. There can only be one admin user per organisation, and I want
the user who registered the earliest for that organisation to be the admin.
I could do this manually but it would take time if I had a lot of users. What would be the best
way to accomplish this?
EDIT:
So I have a number of users like this with the columns. The ones highlighted are the users that has registered the earliest. I want to be able to set those users as an admin user. The only admin user within their organisation and set the rest to 0. 1 (Admin) 0 (Not Admin)
This SQL query will mark users which registered_datetime are lowest in its organisation_id as admin.
UPDATE users SET admin_user = 1
WHERE user_id IN (
SELECT u.user_id FROM users u
WHERE u.registered_datetime IS NOT NULL AND NOT EXISTS(
SELECT 1 FROM users iu
WHERE iu.organisation_id = u.organisation_id AND iu.registered_datetime < u.registered_datetime
)
)
You might want to update all users to admin_user = 0 before this code, so all your users will have their values set.
One caveat here, if two users in one organisation were registered in exact same time, then both of them will be marked as administrators.
Update
I have added u.registered_datetime IS NOT NULL into the WHERE clause to filter out users with NULL in registered_datetime.
MSSQL
In MsSql server I usually solve this problem a in another way, by using ROW_NUMBER():
WITH base AS (
SELECT user_id, ROW_NUMBER() OVER ( PARTITION BY organisation_id ORDER BY registered_datetime ASC ) AS rn
FROM user
WHERE registered_datetime IS NOT NULL
)
UPDATE user SET is_admin = 1
WHERE user_id IN (
SELECT base.user_id FROM base WHERE rn = 1
)
This is too long for a comment.
You are describing three different tables:
Users
Organizations
UserOrganizations
The last has one row per user and per organization. This provides the mapping between the two. This can be called a "mapping" table, "junction" table, or "association" table.
How you implement one admin per organization depends on the database you are using.
You do not need the admin_user column. You need a column isadmin.
When a user is registered, if he is the first in the organization, then the isadmin column has the value 1, otherwise 0
Also, you can use the AAA query to find the administrator
SELECT `table`.`user_id`, MIN(`table`.`registered_datetime`) WHERE `organisation_id`=...

Select entries from a list that do not occur in the query result

I use Postgres 9.1. I am running a query which is like
select count(distinct(user_id)) from users where user_id in (11,32,763,324,45,76,37,98,587);
Here the list of user_ids contains 600 entries. The result I am getting is 597. Thus there are 3 user_ids from the list, which are not present in the users. How do I get to know these 3 user_ids?
Please note that user_id is not the Primary Key of users
DISTINCT in your count-query only makes sense if user_id is not defined UNIQUE.
We don't need it either way for the query you ask for:
SELECT t.user_id
FROM unnest('{11,32,763,324,45,76,37,98,587}'::int[]) t(user_id)
LEFT JOIN users u USING (user_id)
WHERE u.user_id IS NULL;
Beware of NOT IN if NULL values can be involved on either side of the expression! IN / NOT IN with a long value list also scales poorly.
Details:
Optimizing a Postgres query with a large IN
Select rows which are not present in other table

SQL query with OR condition on 2 joined tables

I have a projects table, a users table, a write_permissions table and a read_permissions table. Both read_permissions and write_permissions have 2 columns: project_id and user_id (this is a purposely contrived example, I'm not looking for alternative table settings).
I need for a given user to find all the projects on which he has a write permission or a read permission.
For instance for a user with write permissions on projects A and B, and read permission only on project C, and no permissions for project D, I need to write a query that returns the projects A, B and C.
The query may need to take additional JOIN clauses. For instance I may have a categories table, and a projects_categories table with columns projects_id and user_id, and may want to find all the projects on which a user has write permission and read permission, and that belongs to a given category.
SELECT p.*
FROM (
SELECT project_id
FROM write_permissions
WHERE user_id = 1
UNION
SELECT project_id
FROM read_permissions
WHERE user_id = 1
) sub
JOIN projects p USING (project_id);
UNION without ALL automatically folds duplicates in the result.
SELECT [project_id] FROM [read_permissions] WHERE [user_id]=#user_id
UNION ALL
SELECT [project_id] FROM [write_permissions] WHERE [user_id]=#user_id
this will give you the project that user have read or write premission on them
now you can use it's result

SQL: check one table and enter values into another

I have a very simple MS Access User Table (USER_TABLE) consisting of 3 fields: Customer_Number, User_Name, and Email_Address. I have another table (NEW_USERS) that consist of new requests for Users. It has a User_Status field that is blank by default, and also has the Customer_Number, User_Name, and Email_Address fields.
Half of the new requests that come through are users already existing, so I want to set up a query that will check the USER_TABLE to determine if a new request exists or not, using the Email_Address field checked vs. the Customer_Number field. Complicating this is the fact that 1) Customer_Number is not unique (many Users exists for a single Customer Number) and 2) Users can have multiple accounts for different Customer Numbers. This results in 4 scenarios in the NEW_USERS table when checking vs. the USER_TABLE:
Email_Address does not exist for Customer Number in USER_TABLE (New)
Email_Address exists for Customer Number in USER_TABLE (Existing)
Email_Address does not exist for Customer Number in USER_TABLE, but exists for other Customer Numbers (New-Multi)
Email_Address does exist for Customer Number in USER_TABLE, and also exists for other Customer Numbers (Existing-Multi)
What I would like to do is run these checks and enter the corresponding result (New, Existing, New-Multi or Existing-Multi) into the User_Status field.
This seems like it would be possible. Is it possible to run 4 separate queries to make the updates to NEW_USERS.User_Status?
When you're working in Access, you really need a field that uniquely identifies each record. At the very least, some combination of field, like customerid and email.
Beyond that, since you have a few criteria to satisfy, the easiest way is probably to make a single select statement that compares data between the results of multiple select statements. Look into outer joins for picking the results from one table that are not found in another. Something like -
insert into user_table select customerid, email_address from
(select customerid, email_address from new_users inner join user_table on ...) as expr1,
(select customerid, email_address from new_users outer join user_table on ...) as expr2
where expr1.customerid = expr2.customerid and expr1.new_users = expr2.new_users
I recommend trying out the free stanford course on sql, theres a handy lesson on nesting your select statements - its a good way to get results that fit a lot of criteria. http://class2go.stanford.edu/
As an aside, they do a lot using syntax of 'specifying joins in the where claus' which is increasingly frowned upon, but much easier to understand.