Proper Syntax for 3 table SELECT query - sql

I've got 3 tables:
tblPosts
tblComments
tblUsers
I'm trying to get a listing of Posts along with associated Comments. The tricky part seems to be getting the Posts and Comments to show the proper author (User). This is the closest I get but then the Posts authors are incorrect. I'm grouping my CFOutput on "pid", so I only get each post one time as I would expect.
SELECT tblPosts.pid
, tblPosts.title
, tblPosts.description
, tblPosts.price
, tblPosts.datecreated AS pdate
, tblPosts.image1
, tblComments.comment
, tblComments.datecreated AS cdate
, tblUsers.fname
, tblUsers.lname
FROM tblPosts
LEFT JOIN tblComments ON tblPosts.pid = tblComments.pid
LEFT JOIN tblUsers ON tblComments.uid = tblUsers.uid
Any thoughts?
Thanks!

Since both tables contain an author id, you must to JOIN to tblUser twice: once for posts and once for comments. That means you must use a table alias to differentiate between the two. Something along these lines, where pa is the alias for "Post Author" and ca the alias for "Comment Author".
SELECT p.pid
, p.title
, ...
, pa.fname AS PostAuthorFirstName
, pa.lname AS PostAuthorLastName
, ca.fname AS CommentAuthorFirstName
, ca.lname AS CommentAuthorLastName
FROM tblPosts p
LEFT JOIN tblUsers pa ON pa.uid = p.uid
LEFT JOIN tblComments c ON p.pid = c.pid
LEFT JOIN tblUsers ca ON ca.uid = c.uid

I'm not familiar with all the fields in you tables. Join the post to the users table as well to get the specific users for writing posts.
How about trying this:
SELECT p.pid
,p.title
,p.description
,p.price
,p.datecreated AS pdate
,p.image1
,c.comment
,c.datecreated AS cdate
,u1.fname AS CommentAuthorsName
,u1.lname AS CommentAuthorsLastName
,u2.fname AS PostAuthorName
,u2.lname AS PostAuthorLastName
FROM tblPosts p
LEFT JOIN tblComments c
ON p.pid = c.pid
LEFT JOIN tblUsers u1
ON c.uid = u1.uid
LEFT JOIN tblUsers u2
ON p.uid = u2.uid

Related

Retrieving Records from Multiple Tables issue

Hello i am making schema for purchasing orders these orders can be ordered by certain user and then received by another user.
The issue is when UserID value in Deliveries table is null the query return no records.
UserID value is null because the order is not Delivered yet.
Query
SELECT pu.FirstName as purchase_FirstName, pu.LastName as purchase_LastName,
du.FirstName as delivery_FirstName, du.LastName as delivery_LastName,
po.PurchaseOrderDate,
d.ExpectedDeliveryDate, d.ActualDeliveryDate
FROM dbo.PurchaseOrders po JOIN
dbo.Deliveries d
ON po.PurchaseOrderID = d.PurchaseOrderID JOIN
dbo.Users pu
ON po.UserID = pu.UserID JOIN
dbo.Users du
ON d.UserId = du.UserId;
Schema
Most likely you need a LEFT JOIN here. A little formatting makes this a LOT easier to read. You might take a look at this article to understand the different types of joins. http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
SELECT pu.FirstName as purchase_FirstName
, pu.LastName as purchase_LastName
, du.FirstName as delivery_FirstName
, du.LastName as delivery_LastName
, po.PurchaseOrderDate
, d.ExpectedDeliveryDate
, d.ActualDeliveryDate
FROM dbo.PurchaseOrders po
JOIN dbo.Users pu ON po.UserID = pu.UserID
left JOIN dbo.Deliveries d ON po.PurchaseOrderID = d.PurchaseOrderID
left JOIN dbo.Users du ON d.UserId = du.UserId;

sql select query among 3 tables

I have three tables:
ITEMDISPLAYCOuNTS *this table stores who displayed which posts and howmanytimes
postid, count, whodisplayedid
POSTS *this table stores who posted what?
postid, whopostedid
ASPNET_USERS
userid, username
What I want at the end is who displayed whose post, and how many times, with usernames, not userids:
OUTPUT
UserNameWhoDisplayed, UserNameWhosePost, Count
I wrote the following code, but it is not functioning properly.
SELECT u1.UserName, u2.UserName, ItemDisplayCounts.Count
FROM ItemDisplayCounts AS i, Posts AS p, aspnet_Users AS u1, aspnet_Users AS u2
WHERE p.UserId = u2.UserId AND i.UserId = u1.UserId AND i.PostId = p.PostId
Can anyone suggest any corrections?
I think you want something like this (changed your joins to proper ANSI ones):
select
iu.UserName as UserNameWhoDisplayed,
pu.UserName as UserNameWhosePost,
sum(i.Count) as [Count]
from ItemDisplayCounts as i
inner join aspnet_Users as iu on iu.userid = i.whodisplayedid
inner join posts as p on p.postid = i.postid
inner join aspnet_Users as pu on pu.userid = p.whopostedid
group by
iu.UserName,
pu.UserName
If I am understanding you correctly you do not need to perform any math in the query, since you have the count field in the ITEMDISPLAYCOuNTS table. So, I do believe this will work for you:
SELECT U2.username AS UserNameWhoDisplayed,
U1.username AS UserNameWhosePost,
ID.[Count]
FROM ((POSTS AS P
INNER JOIN ASPNET_USERS AS U1 ON P.whopostedid = U1.userid)
INNER JOIN ITEMDISPLAYCOuNTS AS ID ON P.postid = ID.postid)
INNER JOIN ASPNET_USERS AS U2 ON ID.whodisplayedid = U2.userid

Proper JOIN for Adding a 4th Table to a Query

Asked a similar question HERE but this extends it.
Here's the original query:
SELECT p.pid
, p.title
, p.description
, p.price
, p.datecreated AS pdate
, p.image1
, c.cid
, c.comment
, c.datecreated AS cdate
, pa.fname AS PFName
, pa.lname AS PLName
, ca.fname AS CFName
, ca.lname AS CLName
FROM tblPosts p
LEFT JOIN tblUsers pa ON pa.uid = p.uid
LEFT JOIN tblComments c ON p.pid = c.pid
LEFT JOIN tblUsers ca ON ca.uid = c.uid
ORDER BY p.pid
I need to add a fourth table (tblPostStatus) that holds the status of each post(statusType) which can be one of 2 different values. When I try to add the JOIN I seem to get duped rows, one for each row in tblPostStatus (there are 3 records in this table). This table has fields sid, pid, uid, statusType.
New Query:
SELECT p.pid
, p.title
, p.description
, p.price
, p.datecreated AS pdate
, p.image1
, c.cid
, c.comment
, c.datecreated AS cdate
, pa.fname AS PFName
, pa.lname AS PLName
, ca.fname AS CFName
, ca.lname AS CLName
, ps.statusType
FROM tblPosts p
LEFT JOIN tblUsers pa ON pa.uid = p.uid
LEFT JOIN tblComments c ON p.pid = c.pid
LEFT JOIN tblUsers ca ON ca.uid = c.uid
LEFT JOIN tblPostStatus ps ON p.pid = ps.pid
ORDER BY p.pid
See query result pics:
Do these results look proper or am I doing something incorrectly?
(Summary from chat)
The overall requirements changed a bit. Ultimately "Status" is related to a post, user and comment record, so status was moved to the comment table. An additional requirement was added: identify posts with "claim" comments.
SQL Fiddle
SELECT p.pid
, p.title
, c.cid
, c.comment
, c.statusType
, COALESCE(cnt.HasClaim, 0) AS HasClaim
, pa.fname AS PFName
, pa.lname AS PLName
, ca.fname AS CFName
, ca.lname AS CLName
FROM tblPosts p
LEFT JOIN tblUsers pa ON pa.uid = p.uid
LEFT JOIN tblComments c ON p.pid = c.pid
LEFT JOIN tblUsers ca ON ca.uid = c.uid
LEFT JOIN (
SELECT pid, COUNT(*) AS HasClaim
FROM tblComments
WHERE statusType = 1
GROUP BY pid
) cnt ON cnt.pid = p.pid
ORDER BY p.pid, c.cid

Extra row to SELECT statement, crosstab? Access 2007

I'm working with some biostats people and of course they love SAS. I have a select statement below that works for testing the presence of certain problems a person can have. It's a binary thing so they either do or they don't. If a person has heart problem and a respiratory problem, then their patientID will be listed twice. How can I add an extra column of a 1 or 0 for every morbidity? So, if I have three problems and they are "HEART", "LUNG" and "UTI", an extra column would be generated that has a 1 or 0 based on the presence of that a person had that problem or not.
I suppose I can use Excel to make it a crosstab, but eventually it will need to be in that format. Below is my SELECT statement. Thanks, folks!
EDITED:
TRANSFORM First(Person.PersonID) AS Morbidity
SELECT Person.PersonID, Person.Age, Person.Sex
FROM tblKentuckyCounties INNER JOIN ((tblComorbidity INNER JOIN comorbidVisits ON tblComorbidity.ID = comorbidVisits.comorbidFK) INNER JOIN (Person INNER JOIN tblComorbidityPerson ON Person.PersonID = tblComorbidityPerson.personID) ON tblComorbidity.ID = tblComorbidityPerson.comorbidityFK) ON tblKentuckyCounties.ID = Person.County
WHERE (((tblComorbidity.comorbidityexplanation)="anxiety and depression" Or (tblComorbidity.comorbidityexplanation)="heart" Or (tblComorbidity.comorbidityexplanation)="hypertension" Or (tblComorbidity.comorbidityexplanation)="pressure sores" Or (tblComorbidity.comorbidityexplanation)="tobacco" Or (tblComorbidity.comorbidityexplanation)="uti"))
GROUP BY Person.PersonID, Person.Age, Person.Sex, tblComorbidity.comorbidityexplanation
PIVOT Person.Race;
This is not tested:
TRANSFORM IIf([c.comorbidityexplanation]=
[c.comorbidityexplanation],1,0) AS Morbidity
SELECT p.PersonID, p.Age, p.Sex, p.Race
FROM tblKentuckyCounties kc
INNER JOIN ((tblComorbidity c
INNER JOIN comorbidVisits cv
ON c.ID = cv.comorbidFK)
INNER JOIN (Person p
INNER JOIN tblComorbidityPerson cp
ON p.PersonID = cp.personID)
ON c.ID = cp.comorbidityFK)
ON kc.ID = p.County
GROUP BY p.PersonID, p.Age, p.Sex, p.Race
PIVOT c.comorbidityexplanation

Query that counts the comments for each panelist

I have four tables with the following structure:
panelists (panelist_id, first_name, last_name, etc.)
projects (project_id, title, created_date, etc.)
panelists_on_projects (pp_id, panelist_id, project_id, etc.)
comments (comment_id, panelist_id, project_id, etc.)
Imagine I have four panelists on the same project ("x"), but only 3 of the panelists have left a comment. I am trying to figure out a query that counts the comments for each panelist and returns a zero for the panelist attached to project x, but who has not left a comment.
I tried using the following:
SELECT first_name, last_name, COUNT(comment_id)
from panelists
INNER JOIN comments USING (panelist_id)
WHERE project = x
But I only get results for the 3 panelists who have actually left a comment. Any suggestions?
The outer join is the key part, also I think you forgot about the project in the comments join. When you count by a specific column, null values will not be counted.
select
pj.project_id,
p.panelist_id,
p.firstname,
p.lastname,
totalcomments = count(c.comment_id)
from
project pj
inner join panelists_on_projects pop on pop.project_id = pj.project_id
inner join panelist p on p.panelist_id = pop.panelist_id
left outer join comments c on
c.panelist_id = p.panelist_id
and c.project_id = pj.project_id
where
pj.title = 'X'
group by
pj.project_id,
p.panelist_id,
p.firstname,
p.lastname
Here is my implementation. Although if you know the project_id you can go straight to the panelists_on_projects table.
select
pan.first_name
, pan.last_name
, count(com.comment_id)
from
projects proj
inner join panelists_on_project pop
on proj.panelist_id = pop.panelist_id
inner join panelist pan
on pop.panelist_id = pan.panelist_id
left outer join comments com
on pan.panelist_id = com.panelist_id
and com.project_id = proj.project_id
where
proj.title = 'x'
group by
pan.first_name
, pan.last_name
Without the 2nd condition and com.project_id = proj.project_id on the comments join this would be the count of the total number of comments for all projects of the panelists that were on project 'x'
SELECT P.first_name, P.last_name, COUNT(C.comment_id)
FROM panelists as P
LEFT JOIN panelists_on_projects AS PP ON PP.panelist_id = P.panelist_id
LEFT JOIN projects AS PR PN PP.project_id = PR.project_id
LEFT OUTER JOIN comments As C ON C.panelist_id = P.panelist_id AND C.project_id = PR.project_id
WHERE PR.title = "x"