I've looked all around and spent way to long trying to convert this SQL statement into a Linq statement in VB. I'm sure it would be a good example for others out there - the statement is trying to pull products that have a many-to-many relationship with product categories, and the categories have a hierarchy of parents/children.
Here is the query I am trying to convert:
SELECT P.ProductID, P.ProductName, P.ProductSlug, P.PartNumber
FROM Products AS P
INNER JOIN Products_Categories AS PC ON PC.ProductID = P.ProductID
INNER JOIN Categories AS C ON PC.CategoryID = C.CategoryID
LEFT OUTER JOIN Categories AS P_Cats ON P_Cats.CategoryID = C.Parent
WHERE (C.CategoryID = 9) OR (C.Parent = 9) OR (P_Cats.Parent = 9)
I can get up to the point where I am trying to say "WHERE ... (P_Cats.Parent = 9)" but can't figure that part out.
THANKS!
Figured it out right after posting the question, but here is the answer in case anyone else finds it helpful:
Dim query = (From products In db.Products _
Join PC In db.Products_Categories On PC.ProductID Equals products.ProductID _
Join C In db.Categories On PC.CategoryID Equals C.CategoryID _
Group Join cat In db.Categories On cat.CategoryID Equals C.Parent Into C_Parents = Group _
From cParents In C_Parents.DefaultIfEmpty() _
Where (C.CategoryID = categoryID Or C.Parent = categoryID Or cParents.CategoryID = categoryID) _
And products.IsDeleted = False)
It was the line "From cParents In C_Parents.DefaultIfEmpty()" that I was leaving out.
Related
I have three tables that I would like to select from
Table 1 has a bunch of static information about a user like their idnumber, name, registration date
Table 2 has the idnumber of the user, course number, and the date they registered for the course
Table 3 has the course number, and the title of the course
I am trying to use one query that will select the columns mentioned in table 1, with the most recent course they registered (name and date registered) as well as their first course registered (name and date registered)
Here is what I came up with
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
MIN(l.date_inscr) as mindate, MAX(l.date_inscr) as maxdate, lc.coursename
FROM table1 u,table3 lc
LEFT JOIN table2 l
ON l.idCourse = lc.idCourse
WHERE u.idst = 12787
AND u.idst = l.idUser
And this gives me everything i need, and the dates are correct but I have no idea how to display BOTH of the names of courses. The most recent and the first.
And help would be great.
Thanks!!!
You can get your desired results by generating the min/max date_inscr for each user in a derived table and then joining that twice to table2 and table3, once to get each course name:
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
l.mindate, lc1.coursename as first_course,
l.maxdate, lc2.coursename as latest_course
FROM table1 u
LEFT JOIN (SELECT idUser, MIN(date_inscr) AS mindate, MAX(date_inscr) AS maxdate
FROM table2
WHERE idUser = 12787
) l ON l.idUser = u.idst
LEFT JOIN table2 l1 ON l1.idUser = l.idUser AND l1.date_inscr = l.mindate
LEFT JOIN table3 lc1 ON lc1.idCourse = l1.idCourse
LEFT JOIN table2 l2 ON l2.idUser = l.idUser AND l2.date_inscr = l.maxdate
LEFT JOIN table3 lc2 ON lc2.idCourse = l2.idCourse
As #BillKarwin pointed out, this is more easily done using two separate queries.
Please see the tables:
Sub-Query Method:
select p.Name from Person p where p.PID in
(select mc.PID from M_Cast mc where mc.MID in
(select m.MID from Movie m where lower(title)='anand' ))
Even join is not working:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
group by m.MID
having lower(m.title)='anand'
Your first query works without errors and if you make adjustments like in my few next steps the second one will work also.
Your second query: you can not select only p.Name and group by only m.MID. If it is in select clause and is not a part of aggregate function then you have to use it in group by clause. For example like this:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
group by p.Name;
Your second query also has a HAVING clause having lower(m.title)='anand' but it should be in where clause like this:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
where lower(m.title)='anand'
group by p.Name;
Now that both query are working you need to check if you have a movie with title 'ANAND' in your data. Also you need to check if you have a corresponding MID and PID data in other tables.
I have tested this in MySQL but it will maybe help you even if you use other database to guide you through some mistakes... Here is a small DEMO in MySQL where you will see that data will not be returned if there is no data in one table.
Here is a small DEMO for SQLite where you can see that your first query is working:
http://sqlfiddle.com/#!7/3ec44/1
and here is a small DEMO where you can see that my code is working:
http://sqlfiddle.com/#!7/3ec44/2
Please check the data!
After I have exchanged few comments with OP I have noticed that maybe it is a blank space in data making a problem. So I suggested this:
select p.Name
from Person p
where trim(p.PID, ' ') in (select trim(mc.PID, ' ')
from M_Cast mc
where mc.MID in (select m.MID
from Movie m
where lower(title)='anand'))
This also can be implemented in the second query:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on trim(mc.PID, ' ') = trim(p.PID, ' ')
where lower(m.title)='anand'
group by p.Name;
The problem was that in the query two tables were joined with mc.PID = p.PID and one column had data with blank spaces. So the query was trying to join this data : ' 1' = '1'. TRIM function will remove all the blank spaces in the value and join will then be possible.
SELECT MOVIE.title, person.name
FROM (MOVIE INNER JOIN mcast ON MOVIE.MID = mcast.MID) INNER JOIN person ON mcast.PID = person.PID
WHERE (((MOVIE.title)="ANAND"));
select distinct p.name [Actors in Anand]
Movie m
join M_Cast mc on mc.MID=m.MID
join Person p on p.PID=mc.PID
where m.title="Anand"
order by p.name
I have the following tables in this SQL database (some fields are irrelevant to this question):
I have the following LINQ query:
Dim trips = From tr In db.tbl_Trips _
Join ds In db.tbl_tripDeptStations On tr.trip_ID Equals ds.tds_ID _
Where ds.tbl_Station.stn_County = county _
And tr.trip_StartDate >= startDate _
And tr.trip_EndDate <= endDate _
Select tr.trip_Name, tr.trip_StartDate, tr.trip_EndDate, tr.trip_SmallImage, tr.tbl_TourOperator.tourOp_Name
startDate, endDate and county are variables which I have declared in code above (not shown).
I am trying to show trips which have certain departure stations associated, based upon the county which can be found in the station table.
However, when I run the query, I get no results, and no error messages.
I also have this SQL query which works correctly:
SELECT distinct t.trip_ID, t.trip_Name, t.trip_StartDate, toop.tourOp_Name
FROM tbl_Trip AS t
INNER JOIN
(SELECT tds.tds_trip
FROM tbl_tripDeptStation AS tds
INNER JOIN tbl_station AS s
ON tds.tds_Stn = s.stn_ID
WHERE s.stn_county = 'Greater London'
) AS ds
ON t.trip_ID = ds.tds_trip
INNER JOIN tbl_TourOperator AS toop ON t.tourOp_ID = toop.tourop_id
WHERE t.trip_StartDate >= #StartDate AND t.trip_EndDate <= #EndDate
ORDER BY t.trip_
Can anyone shed some light as to where I might be going wrong?
if you're using entity framework,
var ds = from tds in tbl_tripdeptstation
join s in tbl_station on tds.tds_stn equals s.stn_id
where s.stn_country.equals("somecountry")
select new {tds.trip};
var result = (from t in tbl_trip
join ds2 in ds on t.trip_id equals ds2.trip
join toop in tbl_touroperator on t.tourop_id equals toop.tourop_id
where t.trip_start >= SomeDate AND t.trip_enddate <= EndDate
select new { t.trip_ID, t.trip_Name, t.trip_StartDate, toop.tourOp_Name}).Distinct().OrderBy(r => r.trip_);
In Visual Studio 2010 with ASP.NET 4, I am trying to join several tables together to put the results in a gridview and details view with sqldatasource. In the sqldatasource wizard I have chosen to specify a custom SQL statement or stored procedure and then in the Query Builder to define complex queries such as JOINs, I have tried to generate a SQL statement to join the problem table with speficific columns from other tables. But when I try to test the query I get an error message which says "Cannot call methods on varchar". I am new to sql statements so please can you advise on what is wrong with the statement.
Here is the generated sql statement below
SELECT Problem.ProblemID, Problem.CustomerID, Problem.Summary,
Problem.DateLogged, Problem.DateUpdated, Status.Status, Priority.Priority,
Technician.Name, Technician.Surname, [Skill Group].[Skill Group],
HelpdeskOperator.Name AS Expr1,
HelpdeskOperator.Surname AS Expr2, Problem.NoteID, Problem.ResolutionID
FROM Problem
INNER JOIN Status ON Problem.StatusID = Status.Status.StatusID
INNER JOIN HelpdeskOperator ON
Problem.HelpdeskID = HelpdeskOperator.HelpdeskID AND Status.StatusID = HelpdeskOperator.StatusID
INNER JOIN Priority ON Problem.PriorityID = Priority.PriorityID
INNER JOIN [Skill Group] ON Problem.SkillGroupID = [Skill Group].SkillGroupID
INNER JOIN Technician ON Problem.ProblemID = Technician.ProblemID
AND Status.StatusID = Technician.StatusID AND
Priority.PriorityID = Technician.PriorityID
AND [Skill Group].SkillGroupID = Technician.SkillGroupID
Thank you in advance
Fixed your query:
SELECT p.ProblemID, p.CustomerID, p.Summary, p.DateLogged, p.DateUpdated, s.Status, pr.Priority, t.Name, t.Surname,
sg.* , ho.Name AS Expr1, ho.Surname AS Expr2, p.NoteID, p.ResolutionID
FROM Problem p
INNER JOIN Status s ON p.StatusID = s.StatusID
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
INNER JOIN Priority pr ON p.PriorityID = pr.PriorityID
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
You had duplicate table identifier in your join clause Status.Status.StatusID
I doubt that your Skill Group table contains column [Skill Group] so changed it to return all values from Skill Group
I just think those were the errors, if not I will need more info about your query and table structure.
EDIT:
First it did not return anything for HelpdeskOperator, look at our query:
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
that meanse that here is no such HelpdeskOperator record that is assigned to our problem AND statusid, so either problem id points to noexisting helpdeskoperator or statusid of
this operator is different that problem status id.
next is Skill Group
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
again our problem point to no existing skill group
then Technican
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
here is more work as more checks, technicas must be assigned to our problem with given status and priorityt and be in skill group, BUT our skill group is null? so to check if
there is technican for our problem remove AND sg.SkillGroupID = t.SkillGroupID so you get
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
and see if now we get any technican.
I hope this points you into right direction. You must be sure that there are matching record in every joining table.
I'm having difficulty with a query which displays records according to their fill rate.
For instance, a vacancy can have no bookings or some bookings. If a vacancy has bookings, they can be in the form of 'active [1]', 'pending [0]'. The query I have written so far works if the vacancy has booking records but I can't get it to work if it doesn't have booking records.
My query (which works) for vacancies with a booking is as follows:-
SELECT v.*, j.job_category_name, bu.business_unit_name
FROM vacancy v
INNER JOIN job_category j ON j.job_category_id = v.job_category_id
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id
INNER JOIN booking_status bs ON bs.id = b.booking_status_id
WHERE
v.vacancy_status <> 'revoked' AND
v.vacancy_reference <> 'auto-generated booking' AND
v.business_unit_id IN (series of primary keys) AND
(bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2)
GROUP BY v.vacancy_id
HAVING v.vacancy_limit > count(b.booking_id)
ORDER BY v.vacancy_id DESC
I thought by changing the join of b and bs to LEFT JOIN would have worked, but it hasn't.
Any ideas?
Without a copy of your schema to work from, it's difficult to tell exactly, but when you changed booking and bookingstatus to LEFT JOINs, did you also modify your WHERE clause so that it read something like:
WHERE
v.vacancy_status <> 'revoked' AND
v.vacancy_reference <> 'auto-generated booking' AND
v.business_unit_id IN (series of primary keys) AND
(ISNULL(bs.booking_status_type_id, 1) = 1 OR ISNULL(bs.booking_status_type_id, 2) = 2)
i.e. Ensured that the full WHERE clause would be satisfied, thus not stripping out the records where all the values for columns from booking and bookingstatus were NULL?
Try LEFT OUTER JOIN for the tables for which the joins may return 0 matches.
For eg:- in your case have LEFT OUTER JOIN for b and bs and check