Build a Query to get the informations from a specific user - sql

I'm building a Chat with three Tables.
Conversation, Conversation_reply and user
Conversation Columns
id
user_one
user_two
Conversation_reply Columns
id
user_id
conversation.id
reply
User Columns
id
username
I would like to build a list with the name from the users that are chating with a specific user.
Example, my ID is 711, and I am talking with three persons, I would like to get the username from those three persons.
I'm having some issues building this Query because the user_one and user_two are relative, the ID from the receiver sometimes can be inserted as user_one, or user_two. It depends on which user starts chatting first.
How can I build a Query to do that?
Thanks.

Depending on your RDBMS you can check IF/ELSE, CASE/WHEN syntax.
Based on it you write statement:
SELECT if (user_one=711) user_two ELSE user_one
FROM conversation
where user_one=711 OR user_two=711
This is pseudocode, but idea should be clear.

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

How can I select users based on whether or not there are multiple rows for that user?

I recently had an interview question that was worded something like this:
Select all users from the user table where the user works for multiple businesses and has a salary over 90000 at at least one of the businesses.
Where each row represented a user. Some users had multiple rows (for when they worked for multiple businesses) and each had a businessId.
I'm still pretty new to SQL, I do a lot of basic select and update statements when writing application code, but I'm not sure how to go about doing this. Should I be using count to find out if there are multiple rows for one user? I'm not sure how to structure it with the where clause to check the salary.
Group by the user (for instance the name). Then you can use the having clause to do aggregate operations in the group - meaning for every user
select username
from users
group by username
having count(distinct businessId) > 1
and max(salary) > 90000

Database Design for user defined groups

I'm trying to figure out the best way to design a database to support private user-defined groups. Pretty much identical to how Google Circles are. These are to be for JUST the user, much like circles are - that's why creating a user group design like I found here: https://stackoverflow.com/a/9805712/2580503 would be undesirable.
So far the only solution I can come up with is to have a table like this:
USER_ID | GROUP_ID | ARRAY(USER_ID)
Where the PKEY would actually be a compound key of (USER_ID, GROUP_ID). This way a user could have multiple groups.
Would greatly appreciate any feedback on this proposed solution and would love to hear if there is a better way to do it.
Thanks!
Edit: Just to clarify, GROUP_ID would not reference a separate table, it would just indicate the number group for that user. Also there would be a name etc. for the group as well - just wasn't necessary to include as part of the question.
This must involve at least three (3) tables if you want a normalized design. USERS, USER_GROUPS, and USER_GROUPS_MEMBERS. You are correct that the PK of USER_GROUPS would be a dyad (USER, GROUP). The PK of USER_GROUPS_MEMBERS would be a triad (USER, GROUP, USER).
What about?
Groups (GROUP_ID, USER_ID, GROUP_NAME)
Members (MEMBER_ID, GROUP_ID, USER_ID)
Although Groups might appear backwards, it actually lists the USER_ID that owns a GROUP_ID while Members gives the MEMBER_ID to which could be associated rows that have to do with this USER_ID in the given GROUP_ID.
How about
**Users**
id, name
**Groups**
id, name
**User_Groups**
id, user_id, group_id
**Group_users**
id, user_group_id, user_id
I have separated groups and user_groups assuming that there could be possibilities that you wish to have a few default groups for every user, If this is not the case, you can move the group_name directly to the user_groups and ignore the groups table

sql query with "with and in clause"

i have a table which store user name, hobby and city .hobby field contain different hobby joined using "," operator eg swimming, basket, cricket. I want to search user name who match at least one hobby according to my search criteria.
You should not have multiple attributes in one column. That's one of the number one rules of 3nf database design. Now you have to figure out ways to parse this data. This issue only gets worse and worse each and every day. Seperate the hobbies as multiple rows in your database.
I agree with #JonH that there shouldn't be more than one piece of information in a column. It stops the row being truly atomic.
But you are where you are, and you can use the LIKE clause to return rows that match a substring within a column.
Something like:
select hobbycolumn from hobbytable where hobbycolumn like '%swimming%'
for example
To do this properly you need to restructure your tables if possible. For what you are looking for a possible way would be to have 3 tables. I'm not sure who the city belongs to, so I put it with the user.
1 for user with the following cols:
id
name
city
A table for for hobbies:
id
name
And a user_hobbies join table that allows each user to have multiple hobbies, and each hobby to have multiple users:
id
user_id (foreign key)
hobby_id (foreign key)
Then searching for a user with a certain hobby is:
SELECT user.id, user.name FROM user
INNER JOIN 'user_hobbies' on user_hobbies.user_id=user.id
INNER JOIN 'hobbies' on hobbies.id = user_hobbies.hobby_id
WHERE hobbies.name LIKE "query";

Stored Procedure to get the count using 2 tables

I am trying to write a complicated stored procedure for the first time. My goal is to get the count with some condition from 2 tables.
Consider Merchant table and Email table.
Email table saves the Email invitations sent by the Merchant. Merchant table has all the Merchant Info along with Email IDs.
My goal is to get the count of EmailID s that are in the Merchant table by checking if the Email invitations sent by Merchant has signed up.
I have tried to make this question clear... Hope i am clear.
Thanks in advance..
Why a stored procedure? It sounds like it can be done in a single SQL query.
Let's see if I understand your question correctly: Merchants invite other people to become a Merchant as well and you want a list with the number of accepted invitations per merchant?
Something along those lines:
select MerchantName, count(1)
from Merchants, Emails
where Merchants.Id = Emails.Id
and Emails.SignedUp = 'YES!'
group by MerchantName;
It sounds like there is some confusion in that schema you're describing. Based on what I think you're trying to do I'd suggest you have a Merchant table, an Email table and a MerchantEmail table which links Merchants to email invitations sent.
The way it appears otherwise with a Merchant table that has an Email ID is a many-to-one relationship so that several Merchants could be the recipients of an email. In that case the Signed Up flag would appear in the Merchants table and not in the Email table.
CREATE PROCEDURE GetMerchantsSignedUp
#EmailId INT
AS
SELECT COUNT(*) AS MerchantSignedUp
FROM Merchant, Email
WHERE Merchant.EmailId = Email.Id
AND Merchant.SignedUp = 1
AND Email.Id = #EmailId
Please note that there is some redundancy above which suggests that you need not even include the Email table in the query. Here it acts only to indicate a foreign key relationship.