How do I save multiple values and extra and use them in Sqlite? - sql

I have 2 tables e.g.
First table
ID Value
1 Apple
2 Orange
3 Banana## ...
Second Table
PERSON FRUIT
Amy 1
Peter 2
Charlie 1,2
Dick 2,3
I would like to for example save what fruits the users have in just one column. So that when I call out what Charlie wants, I can somehow receive and output of Apple, Orange; and for Dick - Orange, Banana etc.
I am not really sure where to start on achieving this. Is it possible to do it purely in an SQL select statement alone?

You could implement a link table. For example.. you have a Fruit Table, which stores all the unique fruits, and you have a Person table that stores all unique people.
So you should create a third table that links unique fruits to people for example...
ID FRUIT PERSON
1 1 1
2 1 2
3 2 1
etc... then a select on the link table with the person ID, would bring up all the fruits that person likes.

Related

BigQuery count each item in array across table

I cannot quite find what I'm looking for, so here goes:
I'm looking for a way to get a count of the number of times an item occurs in an array across the entire table.
Imagine you have a table child_names with two columns - user_id and children
I know it's unusual to have two children with same name, but bear with me
.
user_id children
1 Bob, Jane, Bob
2 Jeff, Jane
3 Bob, Matt
4 Jane, John
I am looking for a result that would have two columns
Bob 3
Jane 3
Jeff 1
Matt 1
John 1
So far I have this
SELECT
ARRAY(
SELECT AS STRUCT child, `count`
FROM t.children child
LEFT JOIN (
SELECT AS STRUCT child, COUNT(1) `count`
FROM t.children child
GROUP BY child
) stats
USING(child)
) hashtag
FROM `child_names` t,
UNNEST(children)
But this gives me a count of how many children have that name per parent, not per table.
I get
Bob 2
Jane 1
Jeff 1
Jane 1
Bob 1
Matt 1
etc.
I hope that makes sense. Any help would be appreciated.
Use below
SELECT name, COUNT(*) cnt
FROM child_names,
UNNEST(children) name
GROUP BY name
if applied to sample data in your question - output is

How Do I Filter My Results Based Off Of Other Entries?

I have written a statement that retrieves the person name, as well as the food they've eaten.
Person | Food Eaten
John | Cake
Jack | Ice Cream
Louis | Hot Dog
John | Pineapple Pizza
Now that I've retrieved what foods people have eaten, I would like to remove anyone who has eaten Pineapple Pizza from my list.
What type of clause would I want to use to create a unique list of people who haven't eaten Pineapple Pizza?
You can use not exists :
select t.*
from table t
where not exists (select 1
from table t1
where t1.person = t.person and t1.food = 'Pineapple Pizza'
);
If you know the exact value of the food people have eaten, you can exclude it when you write your WHERE clause.
SELECT t.person, t.food_eaten
FROM eaten_tbl t
WHERE t.food_eaten <> 'Pineapple Pizza';

Categories datatype

I want to check what hobbies a user has and I want to insert it to a database.
I was thinking about making a column Hobbies and to insert the data in a string type in that form : {"Hobby1", "Hobby2", "Hobby3"}
But then the code to filter out the hobbies would be big, is there a more efficient way?
Create a Hobbies table and insert hobbies into that such as Golf, Photography etc.
Then create a UserHobby table to associate a User with a Hobby such that a User can have multiple hobbies.
EG
UserID FirstName
1 Bob
2 John
HobbyID HobbyName
1 Golf
2 Photography
UserHobbyID UserID HobbyID
1 1 1
2 1 2
3 2 2

How to avoid duplicate rows when using simple joins

I have 3 tables.
Table Alpha:
ID NAME
____ _____
Table Beta:
NAME GOALS
_____ _______
Table Charlie:
NAME SCHOOL
_____ _________
I want a table
ID NAME GOALS SCHOOL
______________________________
Note:
ID's are not unique. so for each ID there may be many names. The issue right now is I get MANY MANY duplicate rows when i use inner joins or left joins. Do help (SQL Newbie)
Thank you :))
Name is your foreign key, so if there are two of the same name in Beta, or Charlie, it's going to duplicate the Alpha rows.
What you need to decide is how you'll aggregate the values from the other tables.
You'll probably want the sum of goals for each name, but school, you'll have to pick one. Otherwise you'll have duplicate rows for each school per name.
So, if alpha is
1 John
2 Sue
And Charlie is
John UHT
John MIT
Sue MIT
You'll end up with
1 John UHT
1 John MIT
2 Sue MIT
If Beta has
John 4
John 5
It gets worse. Now John is going to show up 4 times.
So, you'll need to apply aggregate methods. Then do
... Group By Name

Oracle find common value in two different columns

If I have a structure like this:
CREATE TABLE things (
id,
personA varchar2,
personB varchar2,
attribute ...,
)
And I want to find, for a given attribute, if I have at least 1 common person for all my things, how would I go about it?
So if my data is (and it could be more than 2 per attribute):
1, John, Steve, Apple
2, Steve, Larry, Apple
3, Paul, Larry, Orange
4, Paul, Larry, Orange
5, Chris, Michael, Tomato
6, Steve, Larry, Tomato
For Apple, Steve is my common person, For Orange both Paul and Larry are, and for Tomato I have no common people. I don't need a query that returns all of these at once, however. I have one of these attributes and want 0, 1, or 2 rows depending on what kind of commonality I have. I've been trying to come up with something but can't quite figure out.
This will give you your common person / attribute list. I ran it against your sample data and got the expected result. Hope it's at least pointing in the right direction :)
WITH NormNames AS (
SELECT PersonA AS Person, Attribute FROM things
UNION ALL SELECT PersonB AS Person, Attribute FROM things
)
SELECT
Person, Attribute, COUNT(*)
FROM NormNames
GROUP BY Person, Attribute
HAVING COUNT(*) >= 2
If you're on 11gR2 you could also use the unpivot operator to avoid the self-join:
select person, attribute
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
group by person, attribute
having count(*) > 1;
PERSON ATTRIBUTE
---------- ----------
Steve Apple
Paul Orange
Larry Orange
3 rows selected.
Or to just the the people who match the attribute, which I think is what the end of your question is looking for:
select person
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
where attribute = 'Apple'
group by person, attribute
having count(*) > 1;
PERSON
----------
Steve
1 row selected.
The unpivot translates columns into rows. Run on its own it transforms your original six rows into twelve, replacing the original persona/personb columns with a single person and an additional column indicating which column the new row was formed from, which we don't really care about here:
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'));
ID ATTRIBUTE W PERSON
---------- ---------- - ----------
1 Apple A John
1 Apple B Steve
2 Apple A Steve
2 Apple B Larry
3 Orange A Paul
3 Orange B Larry
4 Orange A Paul
4 Orange B Larry
5 Tomato A Chris
5 Tomato B Michael
6 Tomato A Steve
6 Tomato B Larry
12 rows selected.
The outer query is then doing a simple group.
Here's one method.
It implements an unpivot method by cross-joining to a list of numbers (you could use the unpivot method Alex uses) and then joins the result set, hopefully with a hash join for added goodness.
with
row_generator as (
select 1 counter from dual union all
select 2 counter from dual),
data_generator as (
select
attribute,
id ,
case counter
when 1 then persona
when 2 then personb
end person
from
things,
row_generator)
select
t1.attribute,
t1.person
from
row_generator t1,
row_generator t2
where
t1.attribute = t2.attribute and
t1.person = t2.person and
t1.id != t2.id;