SQL selecting multiple record by different variable - sql

Ok, so I have a table Assignment:
[UserId]
[GroupId]
[UpdatedBy]
[UpdatedAt]
Also, I have a function for returning users from a specific group:
select UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId = ?
In Assignment, I want to check all groups that our user is listed and then I want to select ALL users from these groups, without duplicate.
How can I achieve this?
Edit:
Sample output form selecting groupid = 4
for example user "test1" belong to other group where id=2 at the same time and i want selected all users from for example group 2 and 4 (cause in this example test1 said so) without records duplicate

All groups from one UserId (say UserId 10):
select GroupId from Assignment where UserId = 10
Select all users from those groups (without duplicate):
select distinct UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId in (select GroupId from Assignment where UserId = 10)
I hope this is what you wanted.

An inner self join should get you the IDs of the users you're looking for. Join the result with your user table (which you didn't post) to possibly get other information about these users.
SELECT DISTINCT
a2.userid
FROM assignment a1
INNER JOIN assignment a2
ON a2.groupid = a1.groupid
WHERE a1.userid = ?;
(Replace the ? with the ID of the user, you want to start with.)

Assuming your input is a user id:test1 and assuming that you are just looking at one table (Assignment)
DECLARE #UserId INT = 2
;WITH GROUPS AS
(
SELECT DISTINCT GroupId FROM Assignment WHERE UserId = #UserId
)
SELECT distinct assgn.UserName, gps.GroupId FROM Assignment assgn
INNER JOIN
GROUPS gps ON
assgn.GroupId = gps.GroupId
Please let me know if this helps

Related

How to find common matches for different column values in SQL

I have the following table "Friends":
The goal is to find out how many users have the exact same list of friends.
In this case, the result would be user_id 1 and user_id 4 since both user 1 and user 4 are friends with "2" and "3".
I think I am on the right track by using the code below:
SELECT * FROM Friends A, Friends B WHERE A.friend_id=B.friend_id AND A.user_id <> B.user_id
However, I am not able to figure out how to finish the query so that it calculates the matching list of friends. Does anyone have any suggestions?
You didn't provide your SQL type.
For MySQL, you can group concat the friends for every user and cross by this value. The default is ",". Then join the same table to compare by the same list of friends.
SELECT t1.friends, t1.friends FROM
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t1
JOIN
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t2
on t1.friends = t2.friends

How to write a Sql query for retrieving one row from duplicate rows?

i have a User table which has many users but some users are having same first name and Last Name but only one user will have status active . So my requirement is if the user is unique i need the user regardless of Status but if the user is duplicate i need the record having status active.
How can i achieve this in SQL server?
Sorry For the confusion here is the example of User table
my result table should be
Here Steve Jordan is having 2 records so i need the record having status 1
and for records having distinct First name and last name i need all the records regard less of status.
Note : I have a user id as primary key but i am joining on first name and last name because other table doesn't have user id.
SELECT UserId, FirstName, LastName, Status FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY FirstName, LastName
ORDER BY Status DESC) AS rowNum
FROM [User]
) u
WHERE u.rowNum = 1
This essentially groups by first and last name, orders by Status so that active are higher priority, and takes only one of each unique first/last name combination. This ensures that each each unique first/last name combination is in the result set only once, and if there are multiples, the active one is the one returned. If a name combination has multiples, but they are all not active, then only one is returned, chosen arbitrarily.
Ideally, you should have the User ID PK in both tables, as this is much stronger relationally.
EDIT: A bit more complex, but this should give you what you're looking for.
SELECT *
FROM YourOtherTable A
JOIN Users B
ON A.FirstName = B.FirstName AND A.FirstName = B.FirstName
LEFT JOIN
(
SELECT FirstName, LastName FROM User GROUP BY FirstName, LastName HAVING COUNT(FirstName) = 1
) C
ON B.FirstName = C.FirstName AND B.LastName = C.LastName
WHERE B.Status = 1 OR C.FirstName IS NOT NULL
I didn't get you question. But, as per your subject line. It seems like you want the record, which is active, if record is duplicate.
select T.* from yourTable T INNER JOIN (select user, count(*) cnt FROM yourTable GROUP BY user) A ON A.user=T.user
WHERE A.cnt>1 and T.status='A';
If it wasn't your requirement. Then, I would ask you to share your table structure and expected output to understand better.

SQL Server 2008 - Best way to handle public and private records on the same table

I have a table of records on my database which has about a million records. Most of the records are public - meaning all the users on the system are able to view them. However on the same exact table, I have private records as well, usually couple of hundreds for each user. I have about 1K users on the system.
Each record has 3 main columns:
ID - Enum of the record ID. Unique primary key.
UserID - Identifies the record owner. Null = General record available to everyone. ID = Private record available only for this specific user ID.
RecID - Public record ID. Unique for all public records. If a public record is changed by a user, the system duplicates this record with a new ID, but the same RecID.
Example
ID RecID UserID Comments
----------------------------------------------------------------------------
1 1000 NULL General record
2 1000 1 Modification of record ID=1, available only for userID=1
3 1001 NULL General Record
4 1002 NULL General Record
5 1001 2 Modification of record ID=3, available only for userID=2
If User 1 logs into the system, he should get the list of records 2,3,4
If User 2 logs into the system, he should get the list of records 1,4,5
If user 3 logs into the system, he should get the list of records 1,3,4
The query I'm using is as follow:
SELECT *
FROM TB_Records
WHERE UserID = #UserID
OR (RecID IS NULL AND NOT RecID IN (SELECT RecID
FROM TB_Records
WHERE UserID = #UserID)
The problem I'm having is performance. Adding on top of this query sorting filtering and paging results with a performance of 5-10 seconds for each select. When removing the 3rd line of the query - selecting all the records, the performance is much better, 1-2 seconds.
I would like to know if there is a better way to handle such a requirement.
Thanks
This query doesn't make sense. The AND NOT part is unnecessary, because a NULL value of RecID would not do what you expect. I think you mean:
SELECT r.*
FROM TB_Records r
WHERE r.UserID = #UserID OR
(r.UserId IS NULL AND NOT r.RecID IN (SELECT r2.RecID
FROM TB_Records r2
WHERE r2.UserID = #UserID)
First, create indexes on TB_Records(UserId, RecId). That might help. Next, I would try changing this to an explicit left outer join:
select r.*
from TB_Records r left outer join
TB_Records r2
on r2.UserId = #UserId and
r2.RecId = r.RecId
where r.UserId = #UserId or r2.RecId is NULL;
EDIT:
One more attempt, with a different approach. This uses a window function to see if the user is present for a given record:
select r.*
from (select r.*,
max(case when r.UserId = #UserId then 1 else 0 end) over (partition by RecId) as HasUser
from TB_Records r
) t
where r.UserId = #UserId or HasUser = 0;
Otherwise, you should put the execution plans in the question. Sometimes, it a query with union all will optimize better than one with or:
select r.*
from TB_Records r
where r.UserId = #UserId
union all
select r.*
from TB_Records r left outer join
TB_Records r2
on r2.UserId = #UserId and
r2.RecId = r.RecId
where r2.RecId is NULL;

Check if any children exist

Considering these two tables:
Position(positionid, positiontext, reportstopositionid)
User(userid, positionid)
How can I check if a user has any subordinates in one query?
Is it even possible?
A subordinate:
user (a) with positionid has at least one or more subordinates if there exists any users (b) with the positionid of user (a) as reportstopositionid to users (b) corresponding positionid
This will return users who have subordinates:
SELECT *
FROM User u
WHERE EXISTS (
SELECT 1
FROM Position p
WHERE p.reportstopositionid = u.positionid
)
how about this one?
SELECT DISTINCT a.*
FROM user a
INNER JOIN position b
ON a.userID = b.reportstopositionID
the records returned by this query are those which has matching IDs userid on position table at column reportstopositionID
I think you want to do this with a where clause:
select u.*
from user u
where u.positionId in (select reportstopositionid from position p)
This gets the list of users who match, without duplicates.

Getting two rows "in scope" for a PostgreSQL function call: cross join?

I have a user-defined function similarity() that compares two users and returns a score. Right now, the calling query looks like:
SELECT similarity(user1, user2)
FROM (
SELECT users.id
FROM users AS user1
WHERE users.id = 123
)
CROSS JOIN
(
SELECT users.id
FROM users AS user2
WHERE users.id = 456
);
This feels messy. Is there a better way to set up the two users for the function call?
If there is only one from each table (seems likely that id is a PK) then
SELECT similarity((SELECT a FROM users a WHERE a.id=123),
(SELECT b FROM users b WHERE b.id=456));
Simplified form that does exactly the same:
SELECT similarity(a, b)
FROM users a, users b
WHERE a.id = 123
AND b.id = 456;