How to store an element with a lot of fields - sqlite

I want to design a database system (I use SQLite)and in a table where I keep the history, I store some values of an employee (name,surname, id, etc..) One of the fields are some working positions which currently are 3, but in the future may increased to 4 or 5... Which is is more clever to do?
1) Have a table with all the fields (among them: wp1, wp2, wp3) and later add a column for the wp3, or
2) Store all these working positions to a diferrent table where i will have 2 fields id and wp and store the diferrent wp to multiple records?

Is a 'working position' a job title? A record of employment at a previous company?
1 is a bad idea.
You probably want something like this:
create table employees (
id int primary key,
name text not null
);
create table working_positions (
id int primary key,
employee_id int not null references employees(id), /* foreign key to employees table */
...other attributes of a working position...
);

Related

Insert/update trigger updating column value of all rows

I am running into a logical problem.My Trigger is:
create trigger Points1
on Posts
after insert, update
As
declare #value int
declare #postedby int
select #value= Count(Message) from Posts
select #postedby = PostedBy from Posts
update AspNetUsers set User_points = #value * 3
where ( AspNetUsers.Id = #postedby)
I dont know whether i am doing it right or not.
Two tables: AspNetUsers table with User_points column and Id Column as primary key
Posts table with PostId as primary key and PostedBy as foreign key referencing the AspNetUsers table.
Now, i want to compare PostedBy with Id column and if they both are same then update the User_Points column with +3 on every single message he posted.
Now, problem is:
1> It is inserting same number of points in every Row.It should check only currently inserted row and the PostedBy column of that row and then compare with Id column of other table and should Update user's Point of only that Id.
But same result nothing happens
Please tell me how to do it.
thanks in advance
change
select #postedby = PostedBy from Posts
to
select #postedby = PostedBy from INSERTED
'INSERTED' is a magic table that keep insert/updated data in this scope.
Same as this 'DELETED' table keep previous data in update a row

Complex query on sql lite xcode

I'm developing an iOS app and I have a sqlite database with 2 tables related by 1-to-many relationship.
Now I would like to do a query that retrieve all element by first table and in the same time do a count by second table so I can pass the result into my view.
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER,
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
I would like to create a query that returns all artist name and the count of track for each artist name so I can pass this value to my list.
Is it possible? Any help?
Thanks to Joe, your code works well for my, but it's possibile to add new field for store the result of count?
Sorry and if i would take the also all trackname for each artist in the same query?
SELECT a.artistname, count(*)
FROM track t
INNER JOIN artist a
on t.trackartist = a.artistid
GROUP BY a.artistid
Try this:
SELECT a.artistname,
(SELECT COUNT(*) FROM track t
WHERE t.trackartist = a.artistid)
FROM artist a

sqlite include 0 in count

I've got two tables in a SQLite database, and I'm attempting to calculate the count of the routes by rating. It works, but doesn't return 0 for when there isn't a route with that rating. An example rating would be 8, or 11b, or V3.
The query I'm using right now is:
select routes.rating, count(routes.rating) from routes
left join orderkeys on routes.rating = orderkeys.rating
group by routes.rating
order by orderkeys.key
This doesn't return 0 for the ratings that don't have any routes for them, though. The output I get is:
10d|3
7|3
8|2
9|9
10a|5
10b|4
10c|2
11a|3
12b|1
V0|5
V1|7
V2|5
V3|8
V4|3
V5|1
V6|2
V7|3
V8|2
V9|1
What I expect to get is:
7|3
8|2
9|9
10a|5
10b|4
10c|2
10d|3
11a|3
11b|0
11c|0
11d|0
12a|0
12b|1
12c|0
12d|0
V0|5
V1|7
V2|5
V3|8
V4|3
V5|1
V6|2
V7|3
V8|2
V9|1
Here's the schema:
CREATE TABLE routes (
id integer PRIMARY KEY,
type text, rating text,
rope integer,
name text,
date text,
setter text,
color_1 text,
color_2 text,
special_base text,
blurb text,
updater text
);
CREATE TABLE orderkeys (
rating TEXT,
key INTEGER PRIMARY KEY
);
A left join returns all records from the left table, but what you want is all ratings, i.e., all records from the orderkeys table:
SELECT orderkeys.rating,
COUNT(routes.id)
FROM orderkeys
LEFT JOIN routes USING (rating)
GROUP BY orderkeys.rating
ORDER BY orderkeys.key
Try this. I do not like join quite much but it is quite useful when there are a lot of tables:
select routes.rating, count(routes.rating) from routes, rating
where routes.rating = orderkeys.rating
group by routes.rating
order by orderkeys.key

Make own like system for various content

There are three types of content in my database. They are Songs, Albums and Playlists. Albums and Playlists are just collections of songs. And I want to let the user put like for each of them. I made table with columns
LikeId UserId SongId PlaylistId AlbumId
for storing likes. For example if user puts like to song, I put song's id into SongId column and user's id into UserId column. Other columns will be null. It's working good,but I don't like this solution because it's not normalized.
So I want to ask if there are better solutions for this.
You should just create 3 tables - one for User paired with each of Playlist, Song, and Album. They'd look something like:
CREATE TABLE PlaylistLikes
(
UserID INT NOT NULL,
PlaylistID INT NOT NULL,
PRIMARY KEY (UserID, PlaylistID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (PlaylistID) REFERENCES Playlists (PlaylistID)
);
CREATE TABLE SongLikes
(
UserID INT NOT NULL,
SongID INT NOT NULL,
PRIMARY KEY (UserID, SongID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (SongID) REFERENCES Songs (SongID)
);
CREATE TABLE AlbumLikes
(
UserID INT NOT NULL,
AlbumID INT NOT NULL,
PRIMARY KEY (UserID, AlbumID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (AlbumID) REFERENCES Albums (AlbumID)
);
Here, having both columns in the primary key prevents the user from liking the song/playlist/album more than once (unless you want that to be available - then remove it or maybe keep track of that in a 'number of likes' column).
You should avoid putting all 3 different types of likes in the same table - different tables should be used to represent different things. You want to avoid "One True Lookup Table" - here's one answer detailing why: OTLT
If you want to query against all 3 tables, you can create a view which is the result of a UNION between the 3 tables.
How about
LikeId UserId LikeType TargetId
Where LikeType can be "Song", "Playlist" or "Album" ?
Your solution is fine. It has the nice feature that you can set up explicit foreign key relationships to the other tables. In addition, you can verify that exactly one of the values is set by adding a check constraint:
check ((case when SongId is null then 0 else 1 end) +
(case when AlbumId is null then 0 else 1 end) +
(case when PlayListId is null then 0 else 1 end)
) = 1
There is an overhead incurred, of storing NULL values for all three. This is fairly minimal for three values.
You can even add a computed column to get which value is stored:
WhichId = (case when SongId is not null then 'Song'
when AlbumId is not null then 'Album'
when PlayListId is not null then 'PlayList
end);
As a glutton for punishment, I would use three tables: UserLikesSongs, UserLikesPlaylists and UserLikesAlbums. Each contains a UserId and an appropriate reference to one of the other tables: Songs, Albums or Playlists.
This also allows adding additional type-specific information. Perhaps Albums will support a favorite track in the future.
You can always use UNION to combine data from the various entity types.

Multiple Categories in DB

I want to create a page where you can select a category link and then it will show the categories under that category kinda like steps going downward. I want to do my db table like this
table [categories]
pk categoryID
categoryName
parentID
level
that parentID links itself back to the categoryID. Is there any tutorials out there that shows this demonstration I haven't found any. Or is there a better way todo this.
You need to set your table up for a recursive one-to-many relationship, like this making a few assumptions about data types):
CREATE TABLE [Categories]
(
CategoryID int NOT NULL PRIMARY KEY,
CategoryName varchar(255) NOT NULL,
ParentCategoryID int NULL,
-- Level field is not needed; can be dynamically determined
CONSTRAINT FK_Child_to_Parent
FOREIGN KEY (ParentCategoryID)
REFERENCES [Categories] (CategoryID)
)
In order to query this table in general, you need to use a self-join, like this (note the from/join; this is the part you will re-use):
select child.*, parent.*
from Categories child
join Categories parent on child.ParentCategoryID = parent.CategoryID
You can tell when you are looking at a parent category because the value for ParentCategoryID will be NULL. To answer your question of how to get child categories for your page given a parent ID, you can use this:
select child.CategoryID, child.CategoryName
from Categories child
join Categories parent on child.ParentCategoryID = parent.CategoryID
where parent.ParentCategoryID = [some value]
There are tons of tutorials/designs out there if you Google "recursive database table" or related terms; for starters, here is one (picked at random):http://www.tomjewett.com/dbdesign/dbdesign.php?page=recursive.php
If you're using SQL 2005+ you can use a SQL recursive common table expression (CTE).
http://msdn.microsoft.com/en-us/library/ms186243.aspx
http://www.simple-talk.com/sql/t-sql-programming/sql-server-cte-basics/

Resources