Oracle query - How to check if a user is the only one assigned to a project - sql

I am trying to determine if a user is assigned to any project with a specific role (ProjMemberTypeID) and if so, if s/he is the only one.
There is "projMember" table with Project ID, User ID and Project Member Type ID. I need to know if there are any project IDs where this user is the only one with member type id of 1.
Is it also possible to get some project info (like name, ...) joining the requested query with "Project" table, based on Project ID?
I tried this but it only gives me how many users are assigned to projects and if I filter by user ID I get how many projects user is assigned to but don't know how to check if s/he is the only one.
select count(userid), projectid
from projmember
where projmembertypeid = 1 -- and userid=73
group by projectid
order by projectid;

You can use a having clause:
select projectid
from projmember
where projmembertypeid = 1
group by projectid
having min(userid) = 73 and max(userid) = min(userid)
order by projectid;
The query filters on the relevant member type, then aggregates by project; all that is left to do is ensure that the given user was found, and no other.

Related

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`=...

SQL - Ordering the results of a recursive relationship

I've got a databases table of account users. There are two types of account:-
Administrator Account
Standard Account
The data table has two additional columns, Account Number and Parent Account Number. Every record regardless gets assigned a new Account Number, but if an account is a Standard Account, then it gets assigned a Parent Account Number. I can tell who is an administrator by the fact that the Parent Account Number field is NULL.
I'm wanting to print a list of these users, ordered by the administrator account and then any children of that administrator, before moving onto the next administrator account. I'm expecting a list of:-
Administrator (Account 1250, Parent NULL)
Standard Account (Account 1255, Parent 1250)
Standard Account (Account 1256, Parent 1250)
Administrator (Account 1375, Parent NULL)
Standard Account (Account 1403, Parent 1375)
I've did a SQL query of:-
SELECT *
FROM [LWC].[dbo].[AspNetUsers]
ORDER BY AccountNumber, ParentAccountNumber
but this isn't ordering correctly, because every Account Number is different. I presume this would sort as I expected it to, if the AccountNumber was the same for multiple records but it isn't.
Can anyone suggest how I can sort this correctly?
Thanks!
I think simply:
ORDER BY ISNULL(ParentAccountNumber, AccountNumber), ParentAccountNumber, AccountNumber
would do what you want.
As this is a recursive relationship a recursive cte could be used , or a hierarchyId type would / may be better.
Try something like this:
select * from
(SELECT *,
case
when Parent is null then cast((cast(Account as nvarchar) + '0') as int)
else cast((cast(Parent as nvarchar) + '1') as int)
end as OrderCol
FROM [LWC].[dbo].[AspNetUsers])
order by OrderCol

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

Not able to return a field from a child of a parent in SOQL

I have tested the following query which is successful but when apply the query to my custom object it fails. i need to find out what is causing the issue.
SELECT Id, Account.Name FROM Contacts WHERE AccountId in (SELECT Id FROM Account)
Background: There are two entities: Customers and Visits, there can be many visits for any customer. I have created a custom object Customer_Visits__c with several fields. It has a lookup field called Customer__c which looks up to Account (sObject) and stores the Account Id field. The relationship name is CustomerVisitsAccounts. I want to be able to return the customer name field (Account.Name) in the SOQL query, i.e., for each visit record show the name of the customer.
It get success with:
SELECT Id, Name FROM Customer_Visits_c WHERE Customer_c in (SELECT Id FROM Account)
Here is the SOQL string I get fails with:
SELECT Id, Name, CustomerVisitsAccounts__r.Name FROM Customer_Visits_c WHERE Customer_c in (SELECT Id FROM Account)
Here is the error message I get:
ERROR at Row:1:Column:18
Didn't understand relationship 'CustomerVisitsAccounts_r' in field path. If you are attempting to use a custom relationship, be sure to append the '_r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names.

SQL Insert based on role

I have a database with 3 tables:
Table 1 (Department) - This is a table with columns for departments and departmentID's
Table 2 (SecurityMap) - This is a table that maps rolenames to department ID's
Table 3 (customer info) - this is the info that is displayed to users based on their role memberships
I have all of the SELECT based on role functions working.
What I need is to figure out how to insert a specific value into the DepartmentID column within Table 3 by default, based on the users role membership. For instance, when someone is adding a new row to the database - in addition to the data they are supplying within the "add" form, I need a default value inserted into this column. If they are a member of the Marketing role, it should be a 1, if they are a member of the IT role, it should be a 2, etc...
Ideally, this would be done without any knowledge to the user that it is even happening. I would assume that I need to use an "Instead Of" trigger, but I have no idea how to proceed....
Shouldn't be too difficult:
In your app, keep track of the logged-in user and their role.
When your app saves the customer data, make sure it passes the database the role ID as well as the user-entered data (a stored procedure would be ideal here)
When the database processes the supplied data, it saves the role ID into the appropriate column.
this should work provided the rolename-column (or id) is unique in the securityMap-table otherwise the select could return more than one value, maybe you need to select the departmentId differently then.
insert into customer_info(otherdata, departmentId) values('data', (select departmentId from securityMap where rolename = 'userrole'))
Edit:
since you mentioned db_owner maybe this can help you (from http://www.sqlservercentral.com/Forums/Topic411310-338-1.aspx)
WITH CTE_Roles (role_principal_id)
AS
(
SELECT role_principal_id
FROM sys.database_role_members
WHERE member_principal_id = USER_ID()
UNION ALL
SELECT drm.role_principal_id
FROM sys.database_role_members drm
INNER JOIN CTE_Roles CR
ON drm.member_principal_id = CR.role_principal_id
)
SELECT USER_NAME(role_principal_id) RoleName
FROM CTE_Roles
ORDER BY RoleName;
you could join that with the SecurityMap-table to filter out roles like db_owner