Select without Group By Sql - sql

I got some problems with this query i need all my selectors but i only want to group aspnet_Users.Userid how should i do this?
Here is my query:
SELECT
aspnet_Users.UserId, aspnet_Users.UserName,
Friends.Verified, Friends.FriendUserId
FROM
[aspnet_Users]
INNER JOIN
Friends ON Friends.UserId = aspnet_Users.UserId OR Friends.FriendUserId = aspnet_Users.UserId
WHERE
aspnet_Users.UserId IN
(SELECT UserId as Id FROM Friends
WHERE FriendUserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57'
UNION
SELECT FriendUserId as Id FROM Friends
WHERE UserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57')
GROUP BY
aspnet_Users.UserId, aspnet_Users.UserName,
Friends.Verified, Friends.FriendUserId
Stored Procedure structure:
Tables [aspnet_Users] and [Friends]
Columns [aspnet_Users.UserId], [aspnet_Users.UserName], [Friends.Verified], [Friends.FriendUserId]
That is the data that i need to get using the procedure, but the problem is that each user can have multiply friends which means if so there will be multiply Friends values. This is the reason why i can't group using those values cause it gives me dublicates with the wrong value.
Expected Output:
aspnet_Users.UserId (This is the user id of the friend, note that it doesn't mean that its the FriendUserId)
aspnet_Users.UserName (This is the UserName of the friend based on the UserId explained above)
Friends.Verified (True or False. The Verified value in the Friends table on the friendship)
Friends.FriendUserId (The FriendUserId value from the table Friends)

If your relationship is not fully reciprocal in the table Friends, you can use this query.
Otherwise either part of the UNION would work on its own
SELECT U.UserId, U.UserName, F.Verified, F.FriendUserId
FROM Friends F
JOIN aspnet_Users U ON U.UserId=F.UserId
WHERE F.FriendUserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57'
UNION
SELECT U.UserId, U.UserName, F.Verified, F.FriendUserId
FROM Friends F
JOIN aspnet_Users U ON U.UserId=F.FriendUserId
WHERE F.UserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57'

Do you need to group? You aren't using any aggregate functions (eg sum, count)
You haven't made it clear what results you're looking for - I'm guessing all details of users connected with a given user, including the user themselves?
Surely you can just do something like:
Select a.userid, a.username, f.verified, f.userid
From aspnet_users a
Full outer join friends f on f.frienduserid = a.userid
Where a.userid = #userid or f.frienduserid = #userid

You can use DISTINCT
SELECT DISTINCT
aspnet_Users.UserId, aspnet_Users.UserName,
Friends.Verified, Friends.FriendUserId
FROM
[aspnet_Users]
INNER JOIN
Friends ON Friends.UserId = aspnet_Users.UserId OR Friends.FriendUserId = aspnet_Users.UserId
WHERE
aspnet_Users.UserId IN
(SELECT UserId as Id FROM Friends
WHERE FriendUserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57'
UNION
SELECT FriendUserId as Id FROM Friends
WHERE UserId='3d1224ac-f2ad-45d4-aa84-a98e748e3e57')

Related

subquery equivalent for a join solution

We have two tables, User, Emails. They have relationship on User.id == Emails.user_id. If we are interested in those users who have more than one different emails, using join we can accomplish by this JOIN:
SELECT * FROM User
JOIN Emails as EM1 ON User.id = Emails.user_id
JOIN Emails as EM2 ON User.id = Emails.user_id
Where EM1.address_line != EM2.address_line;
How can we achieve the same result using subquery?
You can use a correlated subquery:
select u.*
from users u
where (select count(*)
from emails e
where e.user_id = u.id
) >= 2;
You could use a subquery that only returned user_id from Emails where the user has more than one email address.
Then join this to the User table on that user_id:
SELECT *
FROM User u
INNER JOIN (
SELECT user_id
FROM Emails
GROUP BY user_id
HAVING COUNT(*) > 1
) a ON a.user_id = u.id
The subquery will only return user_id when there is more than one row in the Emails table for that user, which is what you asked for.
Note: SQL is untested.

querying data between three tables

Just wanted confirmation to make sure I'm doing this right before I try it. Kinda weak on joins.
I have three tables:
USER PERSONGROUPTOPERRSON PERSONGROUPS
id userId groupID
firstName groupId groupName
lastName
lastUpdated
I need all users who belong to groups with "volunteer" in the group name.
Would this query be correct?
SELECT
a.firstName, a.lastName, a.lastUpdated
FROM
user as a, persongrouptoperson as b
INNER JOIN ON
a.id = b.userId
WHERE
b.groupId
IN
(SELECT
groupID
FROM
persongroups
WHERE
groupName like '%volunteer%'
);
SELECT
a.firstName, a.lastName, a.lastUpdated
FROM
user as a
INNER JOIN persongrouptoperson as b ON
a.id = b.userId
INNER JOIN persongroups as c ON
b.groupID = c.groupID
WHERE c.groupName like '%volunteer%'
You can do this with inner joins. I added distinct in case your users can be in multiple groups with the word volunteer in it. I also recommend using more intuitive aliases for tables instead of a, b, c.
select distinct
u.firstName
, u.lastName
, u.lastUpdated
from User as u
inner join PersonGroupToPerson as pgp on u.id = pgp.userId
inner join PersonGroup as pg on pgp.groupId = pg.groupId
where pg.GroupName like '%volunteer%'
Not exactly. Try it like this:
SELECT user.firstname, user.lastname, user.lastupdated
FROM user
INNER JOIN persongrouptoperson ON user.id = persongrouptoperson.userid
INNER JOIN persongroups ON persongrouptoperson.groupid = persongroups.groupid
WHERE groupName like '%volunteer%'
The idea is to join all three tables together. You can do this pretty simply with inner joins. You just have to link the common keys. So for instance, the user id field in the user table matches the userid field in the person group to person table. Then the group id field in the person groups table matches the group id field in the person group to person table. Link them with ON statements.
Once the tables are linked, you can imagine that each row contains the user information and the group information. So your where clause can directly call out what you are looking for in that group information.

SQL Querying Incomplete Result

I am having trouble understanding what is wrong with this query or how to properly join it together.
I know that I am missing results from other queries that show both sides of the connections separately using two aliases for the same table.
Pretty much a friendship has two "id"s (source and target) which both map to the same column in the users table.
I believe it is the OR statement that is causing the invalid joining, and if so how is the joining suppose to be done. If not what is the problem?
SELECT DISTINCT u.id, u.first_name, u.last_name
FROM friendships AS f, users AS u
WHERE f.mutual = 'true' -- both are friends
AND (u.id = f.source_id OR u.id = f.target_id) -- this line?
AND f.created_at BETWEEN '2016-01-20' AND '2016-01-27' -- time period they became friends
GROUP BY u.id, u.first_name
ORDER BY u.first_name;
Is it the use of the word "DISTINCT?"
I appreciate the help, I have tried INNER and LEFT JOINS, but my mind is just blanking on this and I can't figure out how to get it to work.
Here is the query that IS WORKING and shows me more users than the above query:
SELECT f.source_id, u1.first_name AS s_firstname, u1.last_name AS s_lastname, f.target_id, u2.first_name AS t_firstname, u2.last_name AS t_lastname
FROM friendships AS f, users AS u1, users AS u2
WHERE f.mutual = 'true'
AND u1.id = f.source_id AND u2.id = f.target_id
AND f.created_at BETWEEN '2016-01-20' AND '2016-01-27';
Friendship Table Definition:
User Table Definition:
You must either
1. UNION (distinct) the projections of your second query on source and target or
2. select distinct users where they are a source or target
SELECT DISTINCT u.id, u.first_name, u.last_name
FROM friendships AS f, users AS u
WHERE f.mutual = 'true' -- both are friends
AND (u.id = f.source_id OR u.id = f.target_id)
AND f.created_at BETWEEN '2016-01-20' AND '2016-01-27'
ORDER BY u.first_name;
This will avoid any "duplicates" between u1 * u2. Either one (or more) friendship records exist (in the given period) or they don't.
SELECT u1.first_name AS s_firstname, u1.last_name AS s_lastname
, u2.first_name AS t_firstname, u2.last_name AS t_lastname
FROM users AS u1
JOIN users AS u2
ON EXISTS (
SELECT 13 FROM friendships f
WHERE u1.id = f.source_id AND u2.id = f.target_id
AND f.mutual = 'true'
AND f.created_at BETWEEN '2016-01-20' AND '2016-01-27';
);

Using binary logic in PostgreSQL JOIN queries

I've got 3 tables that look vaguely like this:
Users
----------
UserID
Name
Phone
User Groups
-----------
GroupID
Activity
Group Membership
---------------
UserID
GroupID
Independent Actives
-------------------
UserID
Activity
The idea is that a user can perform an activity either as part of a group or on their own. What I want to do is return all the people that partake in a certain activity. What I have been able to write so far lets me return all the users which are in groups that undertake that activity. What I want to add to this is the ability to see the people that do the activity independently. This is what I have so far:
SELECT
users.name, users.phone, user_groups.activity
FROM users
INNER JOIN group_membership ON group_membership.userID = users.userID
INNER JOIN user_groups ON user_groups.groupID = group_membership.groupID
WHERE user_groups.activity = 'Knitting';
The above bit works fine and it shows all of the users that are part of groups that do knitting, but I also want it to show all the users that are knitting independently. This is what I have attempted to add:
SELECT
users.name, users.phone, user_groups.activity
FROM users
INNER JOIN group_membership ON group_membership.userID = users.userID
INNER JOIN user_groups ON user_groups.groupID = group_membership.groupID
INNER JOIN independent_activity ON independent_activity.userID = users.userID
WHERE user_groups.activity = 'Knitting' OR independent_activity.activity = 'Knitting';
The problem here is the syntax, I understand the algorithm that I'm trying to do but I don't know how to transfer it into sql and so any help is appreciated.
You could use a UNION in this case
SELECT users.NAME
,users.phone
,user_groups.activity
FROM users
INNER JOIN group_membership ON group_membership.userID = users.userID
INNER JOIN user_groups ON user_groups.groupID = group_membership.groupID
WHERE user_groups.activity = 'Knitting'
UNION
SELECT users.NAME
,users.phone
,independent_activity.activity
FROM users
INNER JOIN independent_activity ON independent_activity.userID = users.userID
WHERE independent_activity.activity = 'Knitting';
You also might want to lookup the differences between a UNION and a UNION ALL and decide the one that suites your requirement.
You've got a working answer from SoulTrain. However, for completeness sake I'd like to mention that you don't have to join all those tables. (You could use outer joins here and remove duplicate matches with DISTINCT, but that's not necessary. You don't have to query the users table twice either. And you don't need UNION for doing the distinct job.)
Simply select from the one table you want to display data from, i.e. the users table, and then use EXISTS or IN to get only those users that are either in one set or another.
select name, phone
from users
where userid in
(
select userid
from independent_actives
where activity = 'Knitting'
)
or userid
(
select userid
from group_membership
where groupid in (select groupid from user_groups where activity = 'Knitting')
)

Select all entities which do not have children -- getting a lot of rows back, is this correct?

I've got 84,000 rows in my Users table. Users are created automatically. So, I thought it would be nice to see how many users actually did anything after being created. I wrote this query:
SELECT COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
WHERE 0 = (SELECT COUNT(*) FROM PlaylistItems WHERE PlaylistId = p.Id)
My intent is to only count users which have no playlist items in any of their playlists. This query returned 74,000 results which seems high.
I'm wondering if this query is selecting all users which have at least one playlist with no items in it. That is, if a user has two playlists -- one empty and one populated -- are they still counted in my query? And, if so, how can I modify it to select only users which have only empty playlists.
If that's vastly more difficult then I might try my hand at counting only users with 1 playlist which is empty.
The database structure is:
Many users. 1:1 user:folder, 1:many folder:playlists, 1:many playlists:playlistItems
A better pattern than counting every single playlist and comparing is simply finding all the users who don't have anything in any playlist. I like NOT EXISTS for this:
SELECT COUNT(u.Id)
FROM dbo.Users AS u
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.PlayLists AS pl
INNER JOIN dbo.PlayListItems AS pli
ON pl.id = pli.PlayListID
INNER JOIN dbo.Folders AS f
ON p.FolderID = f.ID
WHERE f.UserID = u.Id
);
As an aside, calling a column Id in its primary table and something else everywhere else might seem like a good idea, but I find it quite confusing. Why isn't a FolderID called a FolderID everywhere in the data model?
Break down your query:
SELECT u.id, COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join PlaylistItems on PlaylistId = p.Id
group by u.id
This should provide you with a list of all users and the count of the number of rows in playlists by userID. a couple ways to go...
Take a count of all users not in that list:
select count(*) from users where id not in (SELECT u.id FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join PlaylistItems on PlaylistId = p.Id
group by u.id)
MySQL performs poorly on that...same thing using left join:
select count(*)
from users u left join (SELECT u.id, COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join PlaylistItems on PlaylistId = p.Id
group by u.id)a
on a.id = u.id
where a.id is null