I am trying to convert this short SQL statement into linq but I am facing some difficulties, here's my latest attempt, apparently it has an error:
SQL:
select ProductID from products where
categoryID in (select categoryID from categories_sub
where categoryID='15' and category_sub_name = 'chiffon')
Linq:
'15' and 'chiffon' is replaced by parameter 'cID' and 'subCatID' here:
IQueryable<Categories_Sub > cat = (from c in db.Categories_Sub
where c.CategoryID == cID
& c.Category_Sub_ID == subCatID
select c);
var subcat = (from c in db.Products
where cat.Contains(c.ProductID)
select c);
Try
var Result = from p in products
from subc in categories_sub
where subc.categoryID=15 and
subc.category_sub_name = "chiffon" and
p.categoryID = subc.categoryID
select p.ProductID;
Minimally, your code won't compile because there is an extra space before closing generic bracket.
The first line should start with IQueryable<Categories_Sub>.
Then, there is not enough information in your question. What LINQ provider are you using? What makes you think there is an error in query?
I've reformatted the sql to talk about it in a little more depth
1 select ProductID
2 from products
3 where categoryID in
4 (select categoryID
5 from categories_sub
6 where categoryID='15' and
7 category_sub_name = 'chiffon')
Line 3 supposes you're looking for products with a specific categoryID
But your subquery starting on line 4, only returns a list of 0 or more categoryIDs that must = '15'
In which case, why not
1 select ProductID
2 from products
3 where categoryID = '15'
I know this isn't an answer but it was too big to fit inside a comment. I'll try to answer later.
Related
Trying to get the list of product Id's with amount of feedbacks each of them has
Need to count only feedbacks that were given to the product as belonging to specific category (see the SQL script: categoryId == 50). Product can belong to multiple categories.
productId, cnt
14, 0
16, 0
15, 1
09, 2
10, 2
EDIT:
I came up with the LINQ to SQL below, to recreate the logic I expressed trough SQL script below. But the result is not the same. Can't get what's different with LINQ's logic from SQL script's?
LINQ to Sql:
var result =
(
from pcl in db.productCategoryLookup
join p in db.products on pcl.productId equals p.productId
join f in db.feedbacks on p.productId equals f.feedbackId into bb
from g in bb.DefaultIfEmpty()
where (pcl.categoryId == 50)
group p by p.productId into grp
select new
{
productId = grp.Key,
cnt = grp.Count()
} into res1
orderby res1.cnt
select new
{
producetId = res1.productId,
cnt = res1.cnt
}
)
.Take(5)
.ToList();
SQL Script:
SELECT TOP 5
p.productId,
COUNT(f.feedbackId)
FROM ProductCategoryLookup pcl
INNER JOIN Product p
ON p.productId = pcl.productId
LEFT JOIN Feedbacks f
ON f.productId = p.productId
WHERE
pcl.categoryId = 50
GROUP BY
p.productId
ORDER BY
COUNT(f.feedbackId)
Tables:
**Products** table
productId PK
productName string
**ProductCategoryLookup** table. Connects products with Category.
One product can have multiple categories and the feedback goes
for given product in given category.
productId FK
categoryId FK
. . .
**Feedbacks** table. Each product+category pair gets zero or more feedbacks.
feedbackId PK
productId FK
categoryId FK
. . .
**Category** table.
categoryId pk
name
To the answer from AD.Net I added join after 'from' for the productCategoryLookup, and where clause. Works now! Thanks.
(from p in context.Products
select new {Product = p, Count = p.Feedbacks.Any() ? p.Feedbacks.Count() : 0})
.OrderBy(p=>p.Count)
.Take(5)
.Select(p=>p.Product)
.ToList()
Try following query. It may help you.
db.Products.Select(n => new { n.ProductID, count = n.Feedbacks.Count})
.OrderBy(m=>m.count).Take(5).ToList();
Hi I am new to NHibernate and having trouble doing a join on an aggregated set of self. I think showing the SQL I am trying to achieve might help:
The Data Looks Like this:
Message TABLE
ID DIRECTION BATCHID SEQUENCE ISLASTINSEQUENCE
1 Outbound 1 1 0
2 Outbound 1 2 0
3 Outbound 1 3 1
The query looks like this:
--Get all msgs with batchId where full sequence is ready
SELECT *
FROM [Message] M
JOIN (
--Group Msg on batchId and Count Sequence + cross ref using having
SELECT M.BatchId
FROM [Message] M
JOIN (
--Get BatchId of last msg in sequence
SELECT BatchId, Sequence as LastInSequence
FROM [Message]
WHERE Direction = 'Outbound'
AND IsEndOfSequence = 1
) M1 ON M.BatchId = M1.BatchId
WHERE Direction = 'Outbound'
GROUP BY M.BatchId, LastInSequence
HAVING count(1) = M1.LastInSequence
) B ON M.BatchId = B.BatchId
Basically I want to include batches where I have the full sequence
Here is may HNibernate Linq attempt:
var lastInSeqenceMsgs =
from b in Query<Message>(x => x.Direction == MessageDirection.Outbound
&& x.IsEndOfSequence)
select new {b.BatchId, LastInSequence = b.Sequence};
var fullSequenceBatchIds =
from outboundMessage in Query<Message>(x => x.Direction ==
MessageDirection.Outbound)
join lastInSequence in (lastInSeqenceMsgs)
on outboundMessage.BatchId equals lastInSequence.BatchId
group lastInSequence by new {lastInSequence.BatchId, lastInSequence.LastInSequence}
into g
where g.Count() == g.Key.LastInSequence
select g.Key.BatchId;
var allMsgsFromWithCompleteSequences =
from fullSequenceMessage in Query<Message>(x => x.Direction ==
MessageDirection.Outbound)
join test in (fullSequenceBatchIds) on
fullSequenceMessage.BatchId equals test.BatchId
select test;
To which it bombs on the second query (I evaluated the queries - not shown) with the following exception:
Unable to cast object of type 'System.Linq.Expressions.NewExpression' to type 'Remotion.Linq.Clauses.Expressions.QuerySourceReferenceExpression'.
Of which I refined back to the join on self
var fullSequenceBatchIds =
from outboundMessage in Query<Message>(x => x.Direction ==
MessageDirection.Outbound)
join lastInSequence in (lastInSeqenceMsgs)
on outboundMessage.BatchId equals lastInSequence.BatchId
select outboundMessage;
To which I get the exception
"Specified method is not supported."
I am getting brick imprints on my forehead, so some help here would be greatly appreciated.
In general I can just say that the nhibernate Linq provider does NOT support everything what Linq offers.
In addition, nhibernate does NOT support sub queries. It simply doesn't work and you have to work around it somehow.
I have a pretty simple many-to-many table structure (see below) in SQL Server (T-SQL).
I need to:
Select all jobs that don't have an associated person
Select all jobs that are only associated with people who are not visible and/or are deleted
Select all jobs that are deleted.
All of this should return a single table of results
Is this possible in a single join-only query (without using IN/NOT IN, nested selects, unions, or temp tables, etc)?
SCHEMA:
Person
ID
IsVisible
IsDeleted
PersonJobs
PersonID
JobID
Jobs
ID
IsDeleted
I should be able to do each query individually, then join the dataset in code, but I was curious if there's simpler way to do this using joins.
Pseudo code is fine in response, if accurate.
Thanks!
Try
select j.*
from personjobs pj
full join jobs j on pj.jobid = j.id
full join person p on pj.personid = p.id
where pj.personid is null
or p.isdeleted = 1
or p.isvisible = 0
or j.isdeleted = 1
CASE statement is used for identification of the given condition of each raw. If you don't need to know them simply remove it.
Select J.Id, CASE WHEN PersonVisible Is Null THEN '1 - Not Associated'
WHEN PersonVisible = 1 OR PersonDeleted = 1 THEN '2 - Person NotVisible/Deleted'
WHEN J.Deleted = 1 THEN '3 - Deleted Jobs'
ELSE '4 - All Except above' END as Conditions
From Jobs J Left Join
(Select jobId,IsVisible PersonVisible, IsDeleted PersonDeleted
From Person p join PersonJobs pj on p.Id = pj.personId
) X On J.Id = X.jobId
Order by Conditions
I have a Table: Material(ID,Name,MAterialParentID)
SELECT c1.ID,c1.Name as ParentName,c2.id,c2.Name
FROM Material c1 Left JOIN Material c2
ON c1.ID = c2.MaterialParentID
ID ParentName id Name
1 Aluminium 2 Cavity
1 Aluminium 3 Copper
1 Aluminium 4 Flooring
2 Cavity NULL NULL
3 Copper NULL NULL
4 Flooring NULL NULL
5 Glass NULL NULL
I want to convert the above SQL Query to Linq Query using Liq to Entities.
Help Appreciated!
if the table is only for reading you could simply create a view and then when using reverse engineering make sure you have views imported.
or if you did want this done in LINQ here is the MSDN example
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
this is how yours would look
var Material = from M in db.Materials
join M2 in db.Materials on M.ID equals M2.MaterialParentID
select new {ParentID = M.ID, ParentName = M.Name, M2.ID, M2.Name };
i have edited my post above as you can see i have included the ParentID to make all columns unique
For this kind of problem linqpad is your friend.
I'd suggest something like:
var materials = (from m in context.Material
let moreMaterials = (from m2 in context.Material where m2.id == m.id select m2).FirstOrDefault()
select m).ToList();
But you can use linqpad to customise to your query requirements.
I have the following in linq-to-entities
clientprojects = (from p in this.SAPMappingEntities.SAP_Master_Projects
join c in this.SAPMappingEntities.SAP_Master_ProjectPartners on c.project_no equals p.project_no
where c.partner_name.Contains(clientstring)
orderby p.start descending
select new ClientProjects { client = c.partner_name, location = c.city +", "+c.region, project_no = c.project_no, start_dt = p.start, end_dt = p.finish }).Take(50).ToList();
I would like change this query so that for each SAP_Master_Project only get the SAP_Master_ProjectPartners record which has the latest update_dt. How can I do this?
EDIT
There's a project table with a project number and project details including project start and end dates. There's a project partners table with the project partner number, name, project number, update date and other details.
SAP_MASTER_PROJECT
project_no
start
finish
SAP_MASTER_PROJECTPARTNERS
partner_no
project_no
partner_name
city
region
update_dt
When the user enters "ABC" into a text box, the info I want to return is the project number, project start date, project end date plus project partner name, city, and state from the last project partner record for the last 50 projects (based on start date) where the project partner name contains or is like "ABC".
I'm sure there's more than one way to do this, but his SQL gives me the results that I need:
SELECT TOP 50 p.project_no, p.start, p.finish, c.partner_name, c.city, c.region
FROM
(select pp.project_no, pp.partner_name, pp.city, pp.region
from SAP_Master_ProjectPartners pp
where pp.partner_name LIKE #clientstring AND pp.update_dt = (select max(pp1.update_dt)
from SAP_Master_ProjectPartners pp1
where pp1.project_no = pp.project_no)) c
join SAP_Master_Projects p
on (p.project_no = c.project_no)
ORDER BY p.start DESC
EDIT #2
That sql actually returns a few items which have the same update_dt, so I modified the sql to below. Still struggling to convert to linq.
SELECT TOP 50 p.project_no, p.start, p.finish, c.partner_name, c.city, c.region, c.update_dt, c.row_id
FROM SAP_Master_Projects p
join
(select pp.project_no, pp.partner_name, pp.city, pp.region, pp.update_dt, pp.row_id
from SAP_Master_ProjectPartners pp
where pp.partner_name LIKE #clientstring AND pp.row_id = (select TOP 1 row_id
from SAP_Master_ProjectPartners pp1
where pp1.project_no = pp.project_no order by update_dt DESC)) c
on (p.project_no = c.project_no) where p.active_flag = 1
ORDER BY p.start DESC
This query would probably be simpler if you defined an entity relationship between SAP_Master_Projects and SAP_Master_ProjectPartners so the join could be implicit instead of explicit.
Edit Since you can't do that, something like this might work (using let and doing a logical join within a where clause):
var clientProjects =
(
from p in entities.SAP_Master_Projects
let c = entities.SAP_Master_ProjectPartners
.Where(cl => cl.partner_name.Contains(clientstring)
&& cl.project_no == p.project_no
)
.OrderBy(cl => cl.update_dt) // Todo: Might need to be descending?
.FirstOrDefault()
where c != null
orderby p.start descending
select new ClientProjects
{
client = c.partner_name,
location = c.city + ", " + c.region,
project_no = c.project_no,
start_dt = p.start,
end_dt = p.finish
}
)
.Take(50)
.ToList()
;
It sounds like you're trying to come up with the following query:
SELECT *
FROM MasterProjects p
INNER JOIN (SELECT project_no,
partner_name
FROM ProjectPartners o
WHERE o.update_dt = (SELECT MAX(update_dt)
FROM ProjectPartners i
WHERE i.project_no = o.project_no)) c
ON p.project_no = c.project_no
AND p.partner_name = c.partner_name
I'm not entirely sure how to translate this in to LINQ but here is my best attempt:
var clientprojects =
from p in MasterProjects
join c in ProjectPartners on p.project_no == c.project_no
where c.partner_name == (from o in ProjectPartners
where o.project_no == c.project_no
and o.update_dt == (from i in ProjectParters
where o.project_no = i.project_no
select i.update_dt).Max()
select o.partner_name).First();
The above LINQ may not even compile, but hopefully it'll send you in the right direction.
I don't speak your language, sorry. But, for instance, in MySql you might add sort by update_dt DESC LIMIT 1 can you do that or somethign similar?