Querying 2/3 tables with one SQL statement - asp.net

I have three tables: users, projects, user_project
user_project contains user_id, project_id and role_id, where user_id and project_id are both primary keys connected to projects.project_id and users.user_id.
I want to get the the name and surname of all the users from the users table that has to do with a certain project from the projects table through user_project.
What SQL statement do I have to use? I was thinking something like this:
SELECT
users.name, users.surname
FROM users
WHERE users.user_id = user_project.user_id AND projects.project_id = #parameter
I am using SQL Server 2012 and ASP.NET/VB.NET.
Db Diagram:
http://i.imgur.com/lrv52wO.png

SELECT users.name, users.surname
FROM users u
INNER JOIN user_project up
ON u.user_id = up.user_id
WHERE up.project_id = #parameter

You'll need to join to your other tables - either from Users through User_Project all the way to Projects if you want to base your selection on something in the Projects table:
SELECT
u.name, u.surname
FROM users u
INNER JOIN user_project up ON u.user_id = up.user_id
INNER JOIN project p ON p.project_id = up.project_id
WHERE p.project_name = 'something'
or at least to the link table, if you can use the project_id as criteria:
SELECT
u.name, u.surname
FROM users u
INNER JOIN user_project up ON u.user_id = up.user_id
WHERE up.project_id = #parameter
Update: assuming your Role table is connected to Users through again a link table Users_role then you need this to select role name, too:
SELECT
u.name, u.surname,
RoleName = r.Name
FROM users u
INNER JOIN user_project up ON u.user_id = up.user_id
INNER JOIN user_roles ur ON u.user_id = ur.user_id
INNER JOIN role r ON ur.role_id = r.role_id
WHERE up.project_id = #parameter

SELECT
users.name, users.surname
FROM users
inner join user_project
on users.user_id = user_project.user_id
WHERE user_project.project_id = #parameter

This should do it.
SELECT users.name, users.surname
FROM users
INNER JOIN user_project ON user_project.user_id = users.user_id
WHERE (user_project.project_id = #parameter)
The important line here is the line that starts INNER JOIN. You don't need the project table as the project_id column is in user_project. If you wanted to get the project name for example you would need the project table. You would do this by writing another INNER JOIN.
INNER JOIN project ON project.project_id = user_project.project_id
Now that you have joined you can access all the columns in the project table.

Related

SQL to DQ, use sub select

I'm trying to convert a SQL function to a DQL function.
I don't know how to do the following step:
Join on multiple class
Join on temporary table (created by doctrine)
Call a sub select in my function
Here my actual working SQL code.
SELECT ut.token
FROM user_token ut
INNER JOIN factory f ON f.id = ut.factory_id
INNER JOIN article_factory af ON af.factory_id = f.id
INNER JOIN article a ON a.id = af.article_id
WHERE ut.factory_id = (
SELECT f.id
FROM factory f
INNER JOIN article_factory af ON af.factory_id = f.id
INNER JOIN article a ON a.id = af.article_id
WHERE a.id = :article
)
GROUP BY ut.token
In case of, here a screen of my table relation.
article_factory is not an entity or a class. article_factory was created for my relation between article and factory, when I specified a ManyToMany relation.
EDIT: Tryed throught plain SQL, but got issue making link between article and fatory, since DQL only know entity, and Doctrine is creating a table, which I canno't use. With DQL, I still got the same issue than above, I don't know how to properly join my classes, and make my sub-select.

How to use left outer join in my sql query?

Here is my query:
ALTER PROCEDURE sp_logdetails
(
#bookid INT
)
AS
BEGIN
SELECT *
FROM book_lending
LEFT OUTER JOIN student ON student.id = book_lending.id
WHERE bookid = #bookid
END
When i execute above query, it shows only book_lending data, not the student data. Here is my screenshot
And it is my student table data screenshot:
May i know, how to get student data in which particular bookid. I used to set foreign key for book_lending id to student id.
Can anyone guide me to fix this?
Thanks,
Select the specific columns from joined table in your select list. Here bl and s is table alias for better redability. You need to select the columns you want and include them to your select list. below query will select all columns from both tables.
SELECT bl.*, s.*
FROM book_lending bl
LEFT OUTER JOIN student s ON s.id = bl.id
AND bl.bookid = #bookid
You got the fields mixed up in the join:
LEFT OUTER JOIN student ON student.id = book_lending.id
You try to match a student to book lending by ID of both - which is wrong.
Change the code to this and you will start getting results back:
SELECT *
FROM book_lending
LEFT OUTER JOIN student ON student.id = book_lending.studentid
WHERE bookid = #bookid

DQL OneToMany query and performing average

In a OneToMany relationship between the entities:
Composer > Soundtrack
Soundtrack > SoundtrackRating
i want to select each Soundtrack by a given Composer and avergage the SoundtrackRatings for each Soundtrack.
In DQL:
SELECT s.name, (SUM(r.rating)/COUNT(r.rating)) AS rating
FROM Soundtrack AS s
LEFT JOIN SoundtrackRating AS r
WHERE s.composer = :composer AND r.soundtrackId = s.id
GROUP BY s.id
ORDER BY rating DESC
Then i'm passing the :composer instance of type Composer:
$em->createQuery($dql)
->setParameter('composer', $composer)
->getResult();
However in the query result i am getting all Soundtrack entries, no matter what $composer i pass as a parameter. The only difference is that only averages the ratings of the given $composer, the rest averages 0.
Where is the problem in this query?
Figured it out. Removing r.soundtrackId = s.id from the WHERE clause and using WITH in the LEFT JOIN instead:
SELECT s.name, (SUM(r.rating)/COUNT(r.rating)) AS rating
FROM Soundtrack AS s
LEFT JOIN SoundtrackRating AS r WITH r.soundtrackId = s.id
WHERE s.composer = :composer
GROUP BY s.id
ORDER BY rating DESC

sql query for list of all users details in Membership

I'm using .net Membership for user management, I I'd like to make a page for admin that lists all users details.
The Membership system created tables in my sql database server and I'm trying to get all info by query but somehow the query returns nothing.
these are the relevant tables created in the server:
I tried this query: (ms sql 2008)
select u.UserName, m.Email, m.CreateDate, m.LastLoginDate, r.RoleName from dbo.aspnet_Users u, dbo.aspnet_Membership m, dbo.aspnet_UsersInRoles uir, aspnet_Roles r where (u.UserId=m.UserId) and (m.UserId=uir.UserId) and (uir.RoleId=r.RoleId)
but it returns nothing, but when I try:
select u.UserName, r.RoleName from dbo.aspnet_Users u, dbo.aspnet_UsersInRoles uir, aspnet_Roles r where (u.UserId=uir.UserId) and (uir.RoleId=r.RoleId)
It returns a table with the user name and role.
I guess the problem is with the Membership table userID field but I don't know how to explain it really.
Try this:
where (u.UserId=uir.UserId) and (m.UserId=u.UserId) and (uir.RoleId=r.RoleId)
You may try this:
SELECT u.UserName, r.RoleName FROM dbo.aspnet_Users u
INNER JOIN dbo.aspnet_UsersInRoles uir
ON u.UserId=uir.UserId
INNER JOIN aspnet_Roles r
ON uir.RoleId=r.RoleId
Replacing each INNER JOIN with a LEFT JOIN will get you what you want:
SELECT u.UserName, r.RoleName FROM dbo.aspnet_Users u
LEFT JOIN dbo.aspnet_UsersInRoles uir
ON u.UserId=uir.UserId
LEFT JOIN aspnet_Roles r
ON uir.RoleId=r.RoleId

Count the number of elements in sql server table

I have 2 tables which looks like this:
ARTICLES TABLE:
and the output should look like this:
How can I accomplish this using both sql query (i'm using sql server 2005) and using linq to sql query ?
BTW i'm using sql server 2005, asp.net with c# in Visual studio 2008.
Please help me
Thanks in anticipation
Update: Added Linq experssion that can be used if you require an OUTER join.
INNER JOIN
For an inner join ie. only get back the articles that have been bought at least once, you can use the following.
LINQ 2 SQL
from a in Articles
join c in CustomersRecords on
a.Article_Name equals c.Article_Name
group a by new {a.SNo, a.Article_Name} into g
select new
{
SNo = g.Key.SNo,
Article_Name = g.Key.Article_Name,
Total_Items_Bought = g.Count()
}
The above translates to the following SQL
SELECT COUNT(*) AS [Total_Items_Bought], [t0].[SNo], [t0].[Article_Name]
FROM [Articles] AS [t0]
INNER JOIN [CustomersRecord] AS [t1] ON [t0].[Article_Name] = [t1].[Article_Name]
GROUP BY [t0].[SNo], [t0].[Article_Name]
Which when cleaned-up a little gives you
SELECT a.SNo,
a.Article_Name,
COUNT(*) AS Total_Items_Bought
FROM Articles AS a
INNER JOIN CustomersRecord AS c ON a.Article_Name = c.Article_Name
GROUP BY a.SNo, a.Article_Name
LEFT OUTER JOIN
For a left outer join ie. get back all articles event those that have never been bought, you can use the following.
LINQ 2 SQL
from a in Articles
join c in CustomersRecords on
a.Article_Name equals c.Article_Name into apc
select new
{
SNo = a.SNo,
Article_Name = a.Article_Name,
Total_Items_Bought = apc.Count()
}
This translates to the following SQL
SELECT [t0].[SNo], [t0].[Article_Name], (
SELECT COUNT(*)
FROM [CustomersRecord] AS [t1]
WHERE [t0].[Article_Name] = [t1].[Article_Name]
) AS [Total_Items_Bought]
FROM [Articles] AS [t0]
select
A.SNo,
A.Article_Name,
count(C.Article_Name) as Total_Items_Bought
from Articles as A
left outer join CustomersRecord as C
on A.Article_Name = C.Article_Name
group by A.SNo, A.Article_Name
order by A.SNo
Use this for SQL
SELECT
SNO,Article_Name,
(SELECT COUNT(*) FROM CustomersRecord AS cr
WHERE cr.Article_Name = Article_Name) AS Total_Items_Bought
FROM ARTICLES

Resources