SQL Select based on Link Field - sql

I feel like an idiot asking this...
Table 1: users
id serial
person integer
username char(32)
Table 2:persons
id serial
name char(16)
Can I run a query that returns the name field in persons by providing the username in users?
users
1 | 1 | larry123
persons
1 | larry
2 | curly
SQL?
select name from persons where users.person=persons.id and users.username='larry123';
with the desired return of
larry
I have been doing it with two passes until now and think maybe a nested select using a join is what I need
1 | larry

It sounds like you're asking how to do a join in SQL:
SELECT
name
FROM
users JOIN persons ON (users.person = persons.id)
WHERE
users.username = 'larry123';
that is almost the query you wrote. All you were missing was the join clause. You could also do that join like this:
SELECT name
FROM users, persons
WHERE
users.person = persons.id
AND users.username = 'larry123';
I suggest finding a well-written introduction to SQL.

Related

How to use multi table join query efficiently in SQL?

I have Problem statement in Apache Phoenix in which I need to combine three tables for the result.
I have three views over Hbase table, Schema is as follow
Table group:-
pk | Title | ownerId | data
Table Members:-
pk | parentId | Email | data
Table userinfo:-
pk | Email | First Name | Last Name
Now, I want to fetch groups whose title matches with input string if not matched then want to fetch groups whose members have a name that matches with the input string.
I already tried query as follow:-
select * from Group where pk like 'Prefix_%'
and (TITLE like '%A%'
or (OWNER_ID in
(
select parentId from MEMBERS where EMAIL in
( select distinct(EMAIL) from USER_INFO
where pk like 'PREFIX%' and
( FIRST_NAME like '%A%' or LAST_NAME like '%A%')
)
)
) ) order by TITLE limit 5;
But, it's taking too much time also tried Left Join Query with similar but not give expected result.
Please Suggest how can I improve this?

SQL extract unique data from two columns in same table

I have a table friends, which contains the following columns:
friend_id and friend_of (both are storing unique user ids)
lets say the table friends contains the following data:
friend_id | friend_of
-------------------------
123 | 456
456 | 789
456 | 123
So this means that:
user with id=123 have one friend with id=456
user with id=456 have two friends with ids=123 (friend_1) & 789(friend_2)
user with id=789 have one friwnd with id=456
I want to write a query that given a single user id shows every friend that this user has (with their ids).
For example:
if given user with id=123 the output would be users with ids=456
if given user with id=789 the output would be users with ids=456
if given user with id=456 the output would be users with ids=123 and 789
Can you help me with the query I need?
(select friend_id as all_friends from friends where friend_of=ID)
uninon
(select friend_of as all_friends from friends where friend_id=ID)
I suppose you are interested in the case where an id exists only in one of the columns. Above query would address this. Note that union is used here and not union all as unique values are required.
select friend_id, friend_of
where friend_id = '456'
just change ID to get desire ouput
Just use union
Declare #id int = 1;
select f.friendof from
#YourTableName as f where f.friendId = #id
union
select f.friendId from
#YourTableName as f where f.friendof = #id
You can use the query SELECT * FROM friends WHERE friend_id='456', which should get all of the friends of 456. Then do a join on your "users" table using the foreign key friend_of.
EDIT: I didn't realize friends was a two-way relationship. In that case, use a UNION first, some of the other responses talk about it. :)

What kind of SQL join do I need to compress a One to Many relationship into the same view row?

Edit: this isn't to be a dynamic output, the output view structure is fixed.
I am trying to create a SQL Server view that shows a single fixed column row for each user, and flattens out an associated one to many table into that row.
Although the associated table has a one to many relationship, the output table structure is limited to 4 elememts form that table.
My table structure is like so:
User (Id, FirstName, LastName)
Assessment (Id, Date, Location, User_Id)
Topics (Id, Topic, Assessment_Id)
Where the Assessment is joined to the User by the User_Id (One 2 One), and the Topics are joined to the Assessment by the Assessment_Id.
So, if I have three topics for an assessment, I'd want the view to look something like:
User_Id | FirstName | LastName | Date | Location | Topic1 | Topic2 | Topic3 | Topic4 |
1 | dave | toby | 2/2/11 | In situ | apples | pears | lemons | NULL |
My current SQL looks like this:
SELECT User.Id, User.FirstName, User.LastName, Assessment.Date, Assessment.Location, Topic.Topic
FROM User LEFT OUTER JOIN
Assessment INNER JOIN
Topic ON Assessment.Id = Topic.Assessment_Id ON
User.Id = Assessment.User_Id
But this returns a row for each concern - it doesn't compress them to one line. I've played with a few different joins, but haven't been able to get the behaviour I want.
Is it possible to do this in a view?
What do I need to do to make it happen??
Thanks!
There is no such JOIN. SQL has a fixed column output: so you can't add arbritrary numbers of columns. It doesn't matter if it's a view, direct or in a stored procedure.
There are 2 main options
concatenate the many rows into one column which is a popular questions here on SO. One random solution using XML PATH
use dynamic SQL to add a column per row in a stored procedure.
Note: PIVOT is fixed column output too
Edit: for a maximum of 4 child rows
SELECT
P.col1, P.col2,
C1.col1 AS Topic1,
C2.col1 AS Topic2,
C3.col1 AS Topic2,
C4.col1 AS Topic4
FROM
Parent P
LEFT JOIN
Child C1 ON P.Key = C1.FKey AND C1.ID = 1
LEFT JOIN
Child C2 ON P.Key = C2.FKey AND C2.ID = 2
LEFT JOIN
Child C3 ON P.Key = C3.FKey AND C3.ID = 3
LEFT JOIN
Child C4 ON P.Key = C4.FKey AND C4.ID = 4
You can use PIVOT too but I prefer the simpler self joins.
Take a look at PIVOT table functionality - e.g. http://www.help-sql.info/27/9/610208.html and http://blog.sqlauthority.com/2008/05/22/sql-server-pivot-table-example/
Although you will need to know the AssessmentId's before you can write the PIVOT

SQL how to map a row to column?

Database structure with two 1-n connections.
User table
==========
user_id
Attribute table
===============
attribute_id
user_id
attribute_name
Attribute_Value table
=====================
attribute_value_id
attribute_id
attribute_value
Is there a way that I can receive the data in the following row style:
user_id | firstname | lastname
---------------------------
1 | Simon | Smith
2 | John | Doe
Where name is the first attribute_name entry from the Attribute table and lastname the second.
Since you know the names of the values that you are looking for, a join will do the trick.
select
u.user_id,
a1.attribute_value as firstname,
a2.attribute_value as lastname
from User u
inner join Attribute a1
on u.user_id = a1.user_id
and a1.attribute_name = 'name'
inner join Attribute_Value v1
on a1.attribute_id = v1.attribute_id
inner join Attribute a2
on u.user_id = a2.user_id
and a2.attribute_name = 'lastname'
inner join Attribute_Value v2
on a2.attribute_id = v2.attribute_id
or so (did not run this). Use left joins if not everybody has a first or last name.
The only way you can do it with a dynamic number of columns is to use dynamic sql- use one sql statement to generate another by string concatenation.
Edit: I am not sure this is possible in mysql since there's not pivot command. Let me know if you want to see an example query from MS Sql I wrote. It is a similar data model, but there's just a lot more fields / joins.
Also I want to point out that you have a flaw in your design if attribute names wind up not being unique.

Select all items in a table that do not appear in a foreign key of another table

Take for example an application which has users, each of which can be in exactly one group. If we want to SELECT the list of groups which have no members, what would be the correct SQL? I keep feeling like I'm just about to grasp the query, and then it disappears again.
Bonus points - given the alternative senario, where it's a many to many pairing, what is the SQL to identify unused groups?
(if you want concrete field names:)
One-To-Many:
Table 'users': | user_id | group_id |
Table 'groups': | group_id |
Many-To-Many:
Table 'users': | user_id |
Table 'groups': | group_id |
Table 'user-group': | user_id | group_id |
Groups that have no members (for the many-many pairing):
SELECT *
FROM groups g
WHERE NOT EXISTS
(
SELECT 1
FROM users_groups ug
WHERE g.groupid = ug.groupid
);
This Sql will also work in your "first" example as you can substitute "users" for "users_groups" in the sub-query =)
As far as performance is concerned, I know that this query can be quite performant on Sql Server, but I'm not so sure how well MySql likes it..
For the first one, try this:
SELECT * FROM groups
LEFT JOIN users ON (groups.group_id=users.group_id)
WHERE users.user_id IS NULL;
For the second one, try this:
SELECT * FROM groups
LEFT JOIN user-group ON (groups.group_id=user-group.group_id)
WHERE user-group.user_id IS NULL;
SELECT *
FROM groups
WHERE groups.id NOT IN (
SELECT user.group_id
FROM user
)
It will return all group id which not present in user