sql query with "with and in clause" - sql

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";

Related

Finding Values From Result of SQL Query in Different Table

I have multiple tables each connected by PersonID.
PhoneNumber contains columns for phone number type (work, cell, home), phone numbers, a value for whether SMS messaging is enabled, and person IDs.
Person contains names and email addresses and its key is person ID
AttributeValue contains the values for a number of 'custom' attributes (each attribute has a unique 'AttributeId'). The key columns in this table are AttributeId, Value, and EntityId. EntityId matches Person Id
I'm trying to find the corresponding names and email addresses from the PersonTable for the Person ID that meets the following criteria.
FROM [rock].[dbo].[AttributeValue]
WHERE AttributeId='1770';
FROM [rock].[dbo].[PhoneNumber]
WHERE IsMessagingEnabled=0 AND NumberTypeValueId=12
First of all in SQL when you got multiple tables related by one ID you can use joins.
For example I got a table Customer(ID,Name,Firstname) , a table Address(ID, CustomerID, Name, PostalCode, City) and a table Phone(ID,CustomerID,PhoneHome,PhoneMobile)
You can use this kind of query to find addresses and phones corresponding to customers :
SELECT [Address.Name], [Phone.PhoneHome], [Phone.PhoneMobile] FROM Address, Phone
INNER JOIN Address ON [Customer.ID] = [Address.CustomerID]
INNER JOIN Phone ON [Customer.ID] = [Phone.CustomerID]
WHERE [Customer.ID] = "Value"
Hope it will help you, at least you can find good examples of joints on :
http://openclassrooms.com/courses/introduction-aux-jointures-sql (I believe you're french so this is a good french site to learn about it.)
Have a good day
Something like this?
SELECT * FROM Person WHERE PersonID IN (SELECT PersonID FROM ....)

SQL Queries from multiple tables

I am taking a beginner's course in SQL, and have been playing around with some queries. One thing I don't really understand is how to "properly" query multiple tables, that is; compare values from two or more tables.
For instance,
I have a table called Student, holding the username, name, date of birth, and major (just the code. For instance, CS would stand for "Computer Science") of a particular person. I chose to make the username a primary key.
I also have another table called Major holding the major code (such as CS) as a primary key, and the entire major name. For instance, "CS" = "Computer Science", NS = "Neuroscience", etc.
Now, suppose I want to find the name of a major, given a student's username. Following is the imagined pseudocode for this query:
1) In the Student table: Provided the username, check what the major of that particular person is.
select majorcode from Student where username='aUserName';
Doing so correctly gives me the major code.
2) In the Major table: Find the title of the major provided the code.
select majorTitle from Major where majorcode='theMajorCode';
Combinded, I write:
select majorTitle from Major where majorcode=(select majorcode from Student where username='aUserName');
However, now suppose I want BOTH the title of the major (from the Major table) as well as the name of the student (from the Student table).
Any advice on how to do this?
You'll need a join. Something like this - note that any rows in Student that have a majorcode not in Major, or vice-versa, will not be included. If that's not what you want, look into outer joins.
SELECT majorTitle, username
FROM Student s
JOIN Major m ON s.majorcode = m.majorcode
You can of course add a WHERE clause to that query. Reference tables using the aliases ("s" for Student, "m" for Major) to avoid ambiguity.

SQL Cross-Table Referencing

Okay, so I've got two tables. One table (table 1) contains a column Books_Owned_ID which stores a series of numbers in the form of 1,3,7. I have another table (table 2) which stores the Book names in one column and the book ID in another column.
What I want to do is create an SQL code which will take the numbers from Books_Owned_IDand display the names of those books in a new column. Like so:
|New Column |
Book 1 Name
Book 2 Name
Book 3 Name
I can't wrap my head around this, it's simple enough but all the threads I look on get really confusing.
Table1 contains the following columns:
|First_Name| Last_Name| Books_Owned_ID |
Table2 contains the following columns:
|Book_Name|Book_ID|
You need to do an inner join. This is a great example/reference for these
SELECT Book_Name FROM Table2
INNER JOIN Table1
ON Table1.Books_Owned_ID = Table2.Book_ID
EDIT SQL Fiddle
I will work on getting the column comma split working. It wont be a lot extra for this.
EDIT 2 See this answer to build a function to split your string. Then you can do this:
SELECT Book_Name FROM Table2
WHERE Book_ID IN(SELECT FN_ListToTable(',',Table1.Books_Owned_ID) FROM Table1 s)
The core of this centers around data normalisation... Each fact is stored only once (and so is "authoritative"). You should also get into the habit of only storing a single fact in any field.
So, imagine the following table layouts...
Books
Id, Name, Description
Users
Id, Username, EmailAddress, PasswordHash, etc....
BooksOwned
UserId, BookId
So if a single user owns multiple books, there will be multiple entries in the BooksOwned table...
UserId, BookID
1, 1
1, 2
1, 3
Indicates that User 1 owns books 1 through 3.
The reason to do it this way is that it makes it much easier to query in future. You also treat BookId as an Integer instead of a string containing a list - so you don't need to worry about string manipulation to do your query.
The following would return the name of all books owned by the user with Id = 1
SELECT Books.Name
FROM BooksOwned
INNER JOIN Books
ON BooksOwned.BookId = Books.Id
WHERE BooksOwned.UserId = 1
You need a function which takes a comma separated list and returns a table. This is slow and fundamentally a bad idea. Really all this does is convert this way of doing it to be like the data model I describe below. (see ProfessionalAmateur's answer for an example of this).
If you are just starting change your data model. Make a linking table. Like this:
Okay, so I've got two tables. One table (table 1) contains a column Books_Owned_ID which stores a series of numbers in the form of 1,3,7. I have another table (table 2) which stores the Book names in one column and the book ID in another column.
What I want to do is create an SQL code which will take the numbers from Books_Owned_IDand display the names of those books in a new column. Like so:
Person Table
|First_Name| Last_Name| Person_ID |
Book Table
|Book_Name|Book_ID|
PersonBook Table
|PersonID|BookID|
This table can have more than one row for each person.

SQL: check one table and enter values into another

I have a very simple MS Access User Table (USER_TABLE) consisting of 3 fields: Customer_Number, User_Name, and Email_Address. I have another table (NEW_USERS) that consist of new requests for Users. It has a User_Status field that is blank by default, and also has the Customer_Number, User_Name, and Email_Address fields.
Half of the new requests that come through are users already existing, so I want to set up a query that will check the USER_TABLE to determine if a new request exists or not, using the Email_Address field checked vs. the Customer_Number field. Complicating this is the fact that 1) Customer_Number is not unique (many Users exists for a single Customer Number) and 2) Users can have multiple accounts for different Customer Numbers. This results in 4 scenarios in the NEW_USERS table when checking vs. the USER_TABLE:
Email_Address does not exist for Customer Number in USER_TABLE (New)
Email_Address exists for Customer Number in USER_TABLE (Existing)
Email_Address does not exist for Customer Number in USER_TABLE, but exists for other Customer Numbers (New-Multi)
Email_Address does exist for Customer Number in USER_TABLE, and also exists for other Customer Numbers (Existing-Multi)
What I would like to do is run these checks and enter the corresponding result (New, Existing, New-Multi or Existing-Multi) into the User_Status field.
This seems like it would be possible. Is it possible to run 4 separate queries to make the updates to NEW_USERS.User_Status?
When you're working in Access, you really need a field that uniquely identifies each record. At the very least, some combination of field, like customerid and email.
Beyond that, since you have a few criteria to satisfy, the easiest way is probably to make a single select statement that compares data between the results of multiple select statements. Look into outer joins for picking the results from one table that are not found in another. Something like -
insert into user_table select customerid, email_address from
(select customerid, email_address from new_users inner join user_table on ...) as expr1,
(select customerid, email_address from new_users outer join user_table on ...) as expr2
where expr1.customerid = expr2.customerid and expr1.new_users = expr2.new_users
I recommend trying out the free stanford course on sql, theres a handy lesson on nesting your select statements - its a good way to get results that fit a lot of criteria. http://class2go.stanford.edu/
As an aside, they do a lot using syntax of 'specifying joins in the where claus' which is increasingly frowned upon, but much easier to understand.

MS Access - Linking to record through stored ID

I have a few tables set up in Access as follows (forgive the slightly redundant example content):
Table 1:
- ID
- FirstName
- SecondName
Table 2:
- ID
- Details
- PersonID -> Table 1[ID]
Table 3:
- ID
- Group
- PersonDetails -> Table 2[ID]
Table 1 is the base table containing records and retrieving no other information. For example, it could store someone's first and second names, along with an autonumber ID.
Table 2 contains records which, amongst other things, contain a field that links to Table 1 and stores the ID of one of the records held there. With the lookup wizard I can choose to utilise all fields from Table 1, store the ID of the Table 1 record in the Table 2 field and also display the first and second names in the combobox on the form to make choosing a record more intuitive.
In table 3, I need to store the ID of one of the records in Table 2. However, I would also like to again display in the form combobox the first and second names from the related record (in Table 1) whose ID is stored in Table 2. I can't choose to utilise, for example, the PersonDetails field from table 2 as this just puts ID numbers into the combobox - I'd need to do something equivalent of:
Table 2[ID]->[FirstName]
Is this possible to do with the lookup wizard in Access or would I have to look into queries or VBA?
Thanks.
Your query for your combo should look something like this:
SELECT cp.ID, cp.ReferenceName, c.Company, p.FeePerHour
FROM (ClientProfile AS cp LEFT JOIN Clients AS c ON cp.ClientID = c.ID)
LEFT JOIN Pricing AS p ON cp.PricePlanID = p.ID;
The main problem with your query is that you're missing the Parenthesis that are needed when you have multiple joins. If you had another join, you'd need a second set of parenthesis.
I took some liberty and used table aliases. It makes SQL concise and more readable.
If this query still doesn't work it might be because you're trying to join "child tables" to the "main table" without using your Foreign Key fields as the joining field. If this were my database the SQL would look something like this:
SELECT cp.ClientProfileID, cp.ReferenceName, c.Company, p.FeePerHour
FROM (ClientProfile AS cp LEFT JOIN Clients as C ON cp.ClientID = c.ClientID)
LEFT JOIN Pricing AS p ON cp.ClientProfileID = p.ClientProfileID;
Personally, I basically never use just plain ID as a field name. And when creating a foreign key I usually use the same field name as what the original table has. There are exceptions, especially in the case where you need to link back to the same table more than once. Consider the case where you are tracking real estate properties and you have a Buyer and a Seller that are both entities (but different from each other) in the same People table. You would then need to name them something like BuyerID and SellerID but ultimately they would link back to the PersonID in the Person table.
So Here's the table design I would go for. Notice I changed Group to PriceGroup. Watch out for reserved words when programming, not only in SQL but any language. If you name your field Group at some point you'll be trying to "Group on Group" which sounds and looks bad, if nothing else.
Client:
- ClientID
- FirstName
- SecondName
ClientProfile:
- ClientProfileID
- Details
- ClientID (Foreign Key to Client)
Pricing:
- PricingID
- PriceGroup
- ClientProfileID (Foreign Key to ClientProfile)