SQLite - SELECT over multiple entries of the same data/column
-
20-09-2019 - |
Question
I am a bit new to SQLite, and I am having a slight dilemma about my database design. I'll explain. Suppose you and your friends use a number of different nicknames on the Internet (can be more than one per person). What we have here is an ID of the person and a list of all nicknames that this person uses. This is a single entry in a large list. The goal here is to store this data by using SQLite in a way the SELECT statement can be used to fetch all entries that contain the specified nickname.
I have thought about creating a table with two columns, first being the ID (primary key) and the other being a TEXT that holds nicknames in a CSV format. However in this example I don't know how to write the select statement to search and match nicknames stored in CSV.
Ideas?
Solution
For starters, here is what you have
SELECT Name, Nickname FROM MyTable WHERE Nickname = 'Copper';
But I would strongly suggest having a table for Names, and a table for Nicknames used, such that the Nickname has a reference to Names.
CREATE TABLE Users (
UserId INTEGER PRIMARY KEY,
Name TEXT
);
CREATE TABLE Nicknames (
NickNameId INTEGER PRIMARY KEY,
UserId INTEGER REFERENCES Users(UserId),
NickName Text
);
You will find this scheme will give you more control to edit entries, remove them, etc.
Query it with either an INNER JOIN
:
SELECT Users.Name, NickNames.NickName
FROM Users INNER JOIN NickNames ON User.UserId=NickNames.UserId
WHERE NickNames.NickName = 'Copper';
Or a nested query:
SELECT Users.Name
FROM Users
WHERE User.UserId IN (
SELECT NickNames.UserId
FROM NickNames
WHERE NickNames.NickName = 'Copper');
The two are equivalent (in this case) to specifying the join with a WHERE
clause. It works, but it's poor form (it's not as clear as INNER JOIN
):
SELECT Users.Name, NickNames.NickName
FROM Users, NickNames
WHERE User.UserId = NickNames.UserId
AND NickNames.NickName = 'Copper';
OTHER TIPS
Why not just have the following tables:
Person (columns: person_id, person_name)
Nickname (columns: nickname_id, nickname)
Person_Nickname (columns: person_id, nickname_id)
Then you create foreign keys from Person to Person_Nickname and from Nickname to Person_Nickname. This allows a given person to have as many nicknames as you like.
Then, to find all persons which match a given nickname, you can write:
SELECT p.person_name
FROM person.p
, nickname n
, person_nickname pn
WHERE n.nickname = 'nickname of interest'
AND p.person_id = pn.person_id
AND n.nickname_id = pn.nickname_id
You need 2 tables:
- users
- nicknames
In table "users" you have id, name, other optional information on the user. In table "nicknames" you have user_id, nickname.
It's a one to many assosiation. Then to obtain a list of all user nicknames you query it like this (using the user id):
SELECT nicknames.nickname FROM nicknames WHERE nicknames.user_id=id
As a less database like implementation you could do this:
use only one table with 2 fields (user, nickname).
Then you get a list of all john's nicknames (you could use ids, too) associated with a user with a query like this:
SELECT table.nickname FROM table WHERE table.user="john"
The CSV approach works but you would need to implement your own function to add/remove/parse nicknames, and it would almost certainly be slower that the two implementations I explained.