adding a column if record exists in two tables - sql

I have two tables. One is a list of all categories. The other is a list of categories a thing might belong to. A thing can belong to more than one category (it might have more than one record in table two)
So, I have
table:
categories
1, horror
2, romance
3, post modern
4, Canadian
5, English
...
2340
Then another table, thingsToCategories, with two columns (thingID, categoryID)
thingID categoryID
6323-01 1
6323-01 4
6323-01 5
1342-01 2
1342-01 4
Given a thingID, I need a list of all categories (as in select * from table A), with an indication of whether that thing ID exists in table B
So, given thingID of 6323-01, I need a list like this:
1, horror selected
2, romance
3, post modern
4, Canadian selected
5, English selected
My SQL skills are rusty and bad enough I'm not even sure what sort of join to use. Can anyone give any pointers?
(I inherited this database, fwiw)

I think you're looking for an INNER JOIN
SELECT * FROM categories
INNER JOIN thingsToCategories ON categories.CategoryID = thingsToCategories.CategoryID
WHERE thingsToCategories.thingID ='6323-01'
INNER JOIN will ensure a selection based on records that match in both tables.

Related

SQL: identify duplicate value across non-key attribute

Looking for best way to identify if there is a duplicate across keyed values. For instance, if I have t1 called Item, and t2 called SKU, and I want to join them together, and look for an attribute that is only duplicate across that join, and in the SKU table, what is best way to write that SQL?
Example:
Item = A
SKUs = 1, 2, 3
Duplicate Attribute in SKU table = testdupe
Assumption is that value testdupe appears in SKU table under A - 1, and A - 3, but not in A - 2. Expected results would be to show 2 duplicates. This would then repeat for items B, C, D, etc. and their related SKUs if that join contains an attribute that is duplicated.
Hope that lengthy description is clear and thanks in advance for your input!

SQL: How do I find which movie genre a user watched the most? (IMDb personal project)

I'm currently working on a personal project and I could use a little help. Here's the scenario:
I'm creating a database (MS Access) for all of the movies myself and some friends have ever watched. We rated all of our movies on IMDb and used the export feature to get all of the movie data and our movie ratings. I plan on doing some summary analysis on Excel. One thing I am interested in is the most common movie genre that each person watched. Below is my current scenario. Note that the column "const" is the movies' unique IDs. I also have individual tables for each person's ratings and the following tables are the summary tables that make up the combination of all the movies we have watched.
Here's the table I had: http://imgur.com/v5x9Dhg
I assigned each genre an ID, like this: http://imgur.com/aXdr9XI
And here is a table where I have separate instances for each movie ID and a unique genre: http://imgur.com/N0wULo8
I want to find a way to count up all of the genres that each person watches. Any advice? I would love to provide any additional information that you need!
Thank you!
You need to have at least one table which has one row per user and const (movie watched). In the 3 example tables you posted nothing shows who watched which movies, which is information you need to solve your problem. You mention having "individual tables for each person's ratings," so I assume you have that information. You will want to combine all of them though, into a table called PERSON_MOVIE or something of the like.
So let's say your second table is called GENRE and its columns are ID, Genre.
Let's say your third table is called GENRE_MOVIE and its columns are Const and ID (ID corresponds to ID on the GENRE table)
Let's say the fourth table, which you did not post, but which is required, is called PERSON_MOVIE and its columns are person, Const, rating.
You could then write a query like this:
select vw1.*, ge.genre
from (select um.person, gm.id as genre_id, count(*) as num_of_genre
from user_movie um
inner join genre_movie gm
on um.const = gm.const
group by um.person, gm.id) vw1
inner join (select person, max(num_of_genre) as high_count
from (select um.person, gm.id, count(*) as num_of_genre
from user_movie um
inner join genre_movie gm
on um.const = gm.const
group by um.person, gm.id) x
group by person) vw2
on vw1.person = vw2.person
and vw1.num_of_genre = vw2.high_count
inner join genre ge
on vw1.genre_id = ge.id
Edit re: your comment:
So right now you have multiple tables reflecting people's ratings of movies. You need to combine those into a table called PERSON_MOVIE or something similar (as in example above).
There will be 3 columns on the table: person, const, rating
I'm not sure if access supports the traditional create table as select query but ordinarily you would be able to construct such a table in the following way:
create table person_movie as
select 'Bob', const, [You rated]
from ratings_by_bob
union all
select 'Sally', const, [You rated]
from ratings_by_sally
union all
select 'Jack', const, [You rated]
from ratings_by_jack
....
If not, just combine the tables manually and add a third column as shown indicating what users are reflected by each row. Then you can run my initial query.

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.

SQLite JOIN two tables with duplicated keys

I need to join two tables on two different fields. I have table 1 like this:
key productid customer
1 100 jhon
2 109 paul
3 100 john
And table 2 has same fields but aditional data I must relate to first table
key productid customer status date ...
1 109 phil ok 04/01
2 109 paul nok 04/03
3 100 jhon nok 04/06
4 100 jhon ok 04/06
Both "key" fields are autoincrement. Problem is that my relationship fields are repeated several times across result and I need to generate a one-to-one relationship, in such manner that one row from table 2 must be related ONLY ONCE with a row on table 1.
I did a left join on (customer=customer and productid=productid) but relationship came out duplicated, a row from tablet 2 was related many times to rows of table one.
To clarify things...
I have to cross check both tables, table 1 is loaded from an XLS report, table 2 is data from a database that reflects customer transactions with many status data. I have to check if a row from XLS exists in database and then load additional status data. I must produce a report when rows from XLS has no correspondent data on database.
How can accomplish this JOIN, is this possible with only SQL?
You can accomplish this in MS SQL using the sql below. Not sure if SQLite supports this.
select a.*, c.*
from table2 a, ( select min(key) key, productid, customer
from table1
group by productid, customer
) b,
table1 c
where a.productid = b.productid
and a.customer = b.customer
and b.key = c.key
One way to understand this would be to figure out what each table represents exactly. Both tables seem to represent the same thing, with a row representing what you might call a purchase. Why are there two separate tables, then? Perhaps the second table goes into more depth about each purchase? Like jhon bought product 100, and it was 'nok' first and then 'ok'? Is so, then the key (what makes the table unique) for the second table would be all three fields.
You still join on only the two fields that match, but you can't expect uniqueness if there are two rows with the same unique keys.
It helps sometimes to create additional indexes on a table, to see what is truly unique.

Count Instances in Table1 AND link to Table2

Please refer to this background question.
After constructing this COUNT, how would I then link each of these 'Prices' to, for instance, a column called 'Genre' in TableTwo?
e.g.
Table1: Prices, ID
Table2: Genre, ID
Example output:
PRICES, COUNT, Genre
--------------------
13.99, 2, Horror
52.00, 3, Comedy
1.99, 1, Romance
I should hope this question is easy to follow however I will try to elaborate further on request! Cheers!
EDIT:
Yes, this is a much simpler version of what I'm trying to do. As said in the previous question, I have this field name that I want to count the instances of. Now that I have this answer(from the previous question), I now want to link this to another table that I have(to help me analyse some data a little better).
For sake of example, let's say we have a Blockbuster branch that has 2 suppliers. In TableOne I have 'Title'. I have now listed each unique value from Title and counted each one (So in the store I have a unique title called 'Dead Man's Shoes' and there is 10 copies. However, I also have a unique title called 'Touch Of Evil' and because this is more popular, there is 100 copies. I now want to see which supplier these two come from (From TableTwo). Therefore
Example output:
Title, Count, Supplier
------------------------------------
Dead Man's Shoes, 10, Supplier1
Touch Of Evil, 100, Supplier2
Does that help any better?
SELECT t1.Prices, COUNT(t1.ID) AS TheCount, t2.Genre
FROM Table1 AS t1
INNER JOIN Table2 AS t2
ON t1.ID = t2.ID
GROUP BY t1.Prices, t2.Genre
You have to user JOIN function.
Your query would look something like
SELECT * FROM prices JOIN genres ON ( prices.id = genres.id )
and the result would be what you desire. :)
More on this subject here.