This question already has answers here:
Filtering out NULL entries in a SQLite database
(1 answer)
How to filter out null values
(2 answers)
Closed 17 days ago.
I am trying to creat a view of database.
I would need to select only the values from Comments.FK_CommentID which are NOT NULL but I can't seem to know how to solve it.
Here's my view:
CREATE VIEW Comments_of_comments AS SELECT User.Username AS User, Comments.content AS Comment, Comments.FK_CommentID AS 'Commented on' FROM Comments INNER JOIN User ON Comments.UserID = User.UserID ORDER BY User ASC;
Here's the output as of now:
User
Comment
Commented on
Anthony
Hello
3001
Brian
I'm glad
Charlie
I'm sad
3000
Dylan
All ok
3004
Ernie
Let's go
But I would like it to be WHERE Comments.FK_CommentID IS NOT NULL. (Commented on -column)
User
Comment
Commented on
Anthony
Hello
3001
Charlie
I'm sad
3000
Dylan
All ok
3004
If you just want to view your data this way, then add a WHERE clause filtering off the null commented on records:
CREATE VIEW Comments_of_comments AS
SELECT u.Username AS User,
c.content AS Comment,
c.FK_CommentID AS "Commented on"
FROM Comments c
INNER JOIN User u ON c.UserID = u.UserID
WHERE c.FK_CommentID IS NOT NULL
ORDER BY User;
Related
I'm quite new to SQLite and SQL and I am struggling with how to approach the following:
My app will display a list of community members. If I click a member, I can see a list of posts made by the members. A post is an object with name, time and message. How can I store this in an SQLite database so that I can query the database by userid and get the list of posts for a specific user.
I have a Users table with these columns:
USER_ID | NAME
I have a Tweet table with these columns:
USER_ID | NAME | TIME | MESSAGE
My questions are: what the best approach / structure to link these two tables? Do I create a new tweet table for every user, or do I store all tweets in one long table with tweets for user 1 first then for user 2 etc?
I'm not necessarily looking for code dumps but rather an explanation of the logic.
An answer has been given and accepted already, but I wanted to add this.
What you want is one table with users, users. In this table you store your user information (user_id, name).
In your Tweets table, store all tweets for all users. One tweet per row. I'm using tweet_id as PRIMARY KEY for the Tweets table.
You can then 'link' the two in code by doing a JOIN like Dave Swersky said.
For example:
Users
--------------------------
user_id | user_name
--------------------------
123 | 'Terry'
34 | 'Pierre'
Tweets
-----------------------------------------------------------------------
tweet_id | user_id | time | message
-----------------------------------------------------------------------
0 | 123 | 135646 | 'This is a tweet'
1 | 123 | 132646 | 'This is another tweet by Terry'
2 | 34 | 352646 | 'Pierre\'s tweet'
I'm not sure what name is for in your Tweets table. As far as I know tweets do not have a name/subject(?). You do not need to store the user name in both the tweets and users table.
For a quick SQLFiddle, go here: http://www.sqlfiddle.com/#!2/43492/1/0
Join
SELECT u.user_id, u.name, t.time, t.message, t.time
FROM my_users u
INNER JOIN tweets t ON u.user_id = t.user_id
This is a typical "JOIN" scenario where you have a one-to-many relationship between Users and Posts.
Here is an example of a query that would display all users and their posts:
SELECT u.User_ID, u.Name, p.Time, p.Message
FROM Users u INNER JOIN Posts p ON u.User_ID = p.User_ID
This will produce a resultset with four columns. Each "Tweet" will be displayed with its related User record. The 'u.' and 'p.' syntax are table aliases used to make the query easier to read.
You need to have two tables:
1.Users
USER_ID | NAME
2.TWEETS
USER_ID | TIME | MESSAGE
Now for the explanation:
Table 1 is represents the users, there is all the data about the user, like name, phone, address etc.
Table 2 is for all the tweets of all the users, and there is a column that connects between user and his tweet.
In table 2 USER_ID is foreign key, that points to exactly one row in the users table.
To get all the tweets for one user, you can write the next query:
Select TWEETS.MESSAGE, TWEETS.TIME
from Users, TWEETS
where Users.USER_ID = TWEETS.USER_ID
and Users.NAME = "Pierre";
My first ever Stackoverflow question so go easy on me, I am not very experienced with SQLite.
I have a table of football teams
CREATE TABLE IF NOT EXISTS teams (
teamId INTEGER PRIMARY KEY NOT NULL,
name TEXT,
);
and a table of matches
CREATE TABLE IF NOT EXISTS matches (
matchId INTEGER PRIMARY KEY NOT NULL,
homeTeamId INTEGER,
awayTeamId INTEGER,
);
I am trying to work out the SELECT statement that would display the list of matches but would replace both the homeTeamId and the awayTeamId numbers with the team names.
I have tried several variants but because two fields in the matches table join back to the same teams table I am getting either syntax errors or ambiguous column errors.
Sorry for a fairly basic question, any help appreciated.
Geoff
Try this:
select m.matchId, h.name, a.name
from matches m
inner join teams h on h.teamId = m.homeTeamId
inner join teams a on a.teamId = m.awayTeamId
You have not posted the variants you have tried, so I just assume that you the problem was caused by not using aliases (in my example h and a) for the table teams. You have to use at least one alias, if you need to join one table twice.
Thanks for the speedy reply. In the typical way I stumbled on the solution about 15 minutes after I posted my question, my solution was identical to yours except that I didn't bother aliasing the matches table.
Your answer had a little typo in it I think
SELECT m.matchId, h.name, a.name
FROM matches m
INNER JOIN teams h ON h.teamId = m.homeTeamId
INNER JOIN teams a ON a.teamId = a.awayTeamId
-- ^ should be m.awayTeamId
But thanks again for your help!
Geoff
I'm developing a system like SO (completely different topic) and replies and comments are alike with the system we see everyday on StackOverflow.
My question is, I'm loading the question with a Stored PROC, loading replies with another Stored PROC and now I'm adding comment system. Do I need to fetch the comments 1 by 1 for each of the replies on topic?
This means that if I have my page size set to 20 replies, I'll be doing 22 database operations which is more than I was thinking.
I don't think I need to add my database diagram for this question but still here it is:
Questions
-----------
QUESTION_ID
USER_ID
QUESTION_TEXT
DATE
REPLIES
-----------
REPLY_ID
QUESTION_ID
USER_ID
REPLY_TEXT
DATE
COMMENTS
------------
REPLY_ID (fk replies)
USER_ID
TEXT
DATE
You should get all your comments at once.
Then make DataViews from the result with a filter for each reply and bind to that DataView. You could also use linq to entities and just filter out new sets on each bind. Here is a basic pseudo code example:
Get all comments for all replies to question
Bind replies
Implement the OnDataBinding for the reply control that will display the comments
In the OnDataBinding add a filter to the result set for the comments with the same reply ID
Bind the filtered list of comments to the display control for comments
This should work and I have implement the same scenario for similar types of data structures.
Pabuc,
For your initial Question, why not get all the results using a single Query for the given question / reply ?
select reply_text, user_id
from REPLIES
order by DATE asc
Also, as you pointed out, except for the minor differences, the question and answer have almost the same attributes as that of a post.
Wouldn't a model like the one below make more sense? The Question and Answer are both "posts" with the only difference being an answer has the question as the parent and the question has no parent.
Create table post -- question/reply (
post_id number,
parent_post_id number, -- will be null if it is the question, will have the question id
-- if it is a reply to a question
post_text varchar2(4000),
user_id number,
post_date date);
-self referential foreign key
Alter table post
add constraint foreign key (parent_post_id) references post(post_id);
--comments to all posts (questions/replies).
create table comments(
comment_id number,
post_id number,
comment_txt varchar2(140),
comment_user_id number,
comment_date date
);
alter table comments add constraint fk_comments_post
foreign key (post_id) references post(post_id).
-- for a given Question (post) id, you can get all the replies and posts using...
select replies.*,
comments.*
from posts replies,
comments
where replies.parent_id = :Question_id --input
and comments.post_id = replies.post_id
You might have to add an order by clause to get the results based on points, updated_timestamp or any other attribute as needed.
A sample case scenario - I have a form with one question and multiple answers as checkboxes, so you can choose more than one. Table for storing answers is as below:
QuestionAnswers
(
UserID int,
QuestionID int,
AnswerID int
)
What is the best way of updating those answers to the database using a stored proc? At different jobs I've seen all spectrum, from simply deleting all previous answers and inserting new ones, to passing list of answers to remove and list of answers to add to the stored proc.
In my current project performance and scalability are pretty important, so I'm wondering what's the best way of doing it?
Thanks!
Andrey
If I had a choice of table design, and the following statements are true:
You know the maximum choices count per question/
Each choice is a simple checked/unchecked.
Each answer be classified as correct/wrong rather than marked by some scale. (Like 70% right.)
Then considering performance I would considered the following table instead of the one you presented:
QuestionAnswers
(
UserID int,
QuestionID int,
Choice1 bool,
Choice2 bool,
...
ChoiceMax bool
)
Yes, it is ugly in terms of normalization but that denormalization will buy performance and simplify queries -- just one update/insert for one question. (And I would update first and insert only if affected rows equals to zero.)
Also detecting whether the answer was correct will be also more simple -- with the following table:
QuestionCorrectAnswers
(
QuestionID int,
Choice1 bool,
Choice2 bool,
...
ChoiceMax bool
)
All you need to do is just to lookup for the row in QuestionCorrectAnswers with the same combination of choices as user answered.
If the questions are always the same, then you'd never delete anything - just run an update query on all changed Answers.
Update QuestionAnswers
SET AnswerID = #AnswerID
WHERE UserID = #UserID AND QuestionID = #QuestionID
If for some reason you still need to do some delete/insert - I'd check which QuestionIDs already exist (for the given UserID) so you do a minimum of Delete/Insert.
Updates are just far faster than Delete then Insert, plus you don't make any identity columns skyrocket.
I presume you load the QuestionAnswers from DB upon entering the page, so the user can see which answers he/she gave last time - if you did you already have the necessary data in memory, for determining what to delete, insert and update.
Andrey: If the user (userid=1) selects choices a(answerid=1) & b(answerid=2) for question 1(questionid=1) and later switches to c (a-id=3) & d(a-id=4), you would have to check, then delete the old and add the new. If you choose to follow the other approach, you would not be checking if a particular record exists (so that you can update it), you would just delete old records and insert new records. Anyways, since you are not storing any identity columns, I would go with the latter approach.
It is a simple solution:
Every [Answer] should have integer value (bit) and this value is unique for current Question.
For example, you have Question1 and four predefined answers:
[Answer] [Bit value]
answer1 0x00001
answer2 0x00002
answer3 0x00004
answer4 0x00008
...
So, you SQL INSERT/UPDATE will be:
declare #checkedMask int
set #checkedMask = 0x00009 -- answer 1 and answer 4 are checked
declare #questionId int
set #questionId = 1
-- delete
delete
--select r.*
r
from QuestionResult r
inner join QuestionAnswer a
on r.QuestionId = a.QuestionId and r.AnswerId = a.AnswerId
where r.QuestionId = #questionId
and (a.mask & #checkedMask) = 0
-- insert
insert QuestionResult (AnswerId, QuestionId)
select
AnswerId,
QuestionId
from QuestionAnswer a
where a.QuestionId = #questionId
and (a.mask & #checkedMask) > 0
and not exists(select AnswerId from QuestionResult r
where r.QuestionId = #questionId and r.AnswerId = a.AnswerId)
Sorry to resurect an old thread. I would have thought the only realistic solution is to delete all responses for that question, and create new rows where the checkbox is ticked. Having a column per answer may be efficient as far as updates go, but the inflexibility of this approach is just not an option. You need to be able to add options to a question without having to redesign your database.
Just delete and re-insert. Thats what databases are designed to do, store and retrieve lots of rows of data.
I disagree that regent's answer is denormalized. As long as each answer is not dependent on another column, and is only dependent on the key, it is in 3rd normal form. It is no different than a table with the following fields for a customer name:
CustomerName
(
name_prefix
name_first
name_mi
name_last
name_suffix
city
state
zip
)
Same as
QuestionAnswers
(
Q1answer1
Q1answer2
Q1answerN
)
There really is no difference between the "Question" of name and the multiple answers which may or may not be filled out and the "Question" of the form and the multiple answers that may or may not be selected.
I asked this question previously but the answers weren't what I was looking for.
I created a table in Asp.net without using code. It contains two columns.
YourUserId and FriendUserId
This is a many to many relationship.
Heres what I want:
There can be multiple records with your name as the UserId, there can also be multiple records with FriendUserId being the same...but there cannot be multiple records with both being the same. For example:
Dave : Greg
Dave : Chris
Greg : Chris
Chris : Greg
is good
Dave : Greg
Dave : Greg
is not good.
I right clicked on the table and chose Indexes/Keys. I then put both columns in the columns section and chose to make the unique. I thought this would make them unique as a whole but individually not unique.
If you go to the Dataset, it show keys next to both columns and says that there is a constraint with both columns being checked.
Is there a way of just making sure that you are not inserting a duplicate copy of a record into the table without individual columns being unique?
I tried controling it with my sql insert statement but that did not work. This is what I tried.
INSERT INTO [FriendRequests] ([UserId], [FriendUserId]) VALUES ('"+UserId+"', '"+PossibleFriend+"') WHERE NOT EXIST (SELECT [UserId], [FriendUserId] FROM [FriendRequests])
That didn't work for some reason.
Thank you for your help!
You should create a compound primary key to prevent duplicate rows.
ALTER TABLE FriendRequests
ADD CONSTRAINT pk_FriendRequests PRIMARY KEY (UserID, FriendUserID)
Or select both columns in table designer and right click to set it as a key.
To prevent self-friendship, you'd create a CHECK constraint:
ALTER TABLE FriendRequests
ADD CONSTRAINT ck_FriendRequests_NoSelfFriends CHECK (UserID <> FriendUserID)
You can add the check constraint in the designer by right clicking anywhere in the table designer, clicking "Check constraints", clicking "add", and setting expression to UserID <> FriendUserID
You might want to look at this question
Sounds like you need a composite key to make both fields a single key.
I have a better idea. Create a new table. Called FriendRequestRelationships. Have the following columns
FriendRelationshipId (PRIMARY KEY)
UserId_1 (FOREIGN KEY CONSTRAINT)
UserId_2 (FOREIGN KEY CONSTRAINT)
Put a unique constraint to only allow one relationship wit UserId_1 and UserId_2. This table now serves as your many-to-many relationship harness.
Create a scalar function that can return the FriendUserId for a UserId, lets say it's called fn_GetFriendUserIdForUserId
You can now display your relationships by running the following query
SELECT dbo.fn_GetFriendUserIdForUserId(UserId_1) AS 'Friend1',
dbo.fn_GetFriendUserIdForUserId(UserId_2) AS 'Friend2',
FROM FriendRelationshipId