Distinct on one column in linq with joins - linq

I know we can get distinct on one column using following query:
I know we can get distinct on one column using following query:
SELECT *
FROM (SELECT A, B, C,
ROW_NUMBER() OVER (PARTITION BY B ORDER BY A) AS RowNumber
FROM MyTable
WHERE B LIKE 'FOO%') AS a
WHERE a.RowNumber = 1
I have used similar sql query in my case where i am joining multiple tables but my project is in mvc4 and i need linq to entity equivalent of the same. Here is my code:
select * from
(
select fp.URN_No,
ROW_NUMBER() OVER
(PARTITION BY pdh.ChangedOn ORDER BY fp.CreatedOn)
as num,
fp.CreatedOn, pdh.FarmersName, pdh.ChangedOn, cdh.Address1, cdh.State, ich.TypeOfCertificate, ich.IdentityNumber, bdh.bankType, bdh.bankName,
pidh.DistrictId, pidh.PacsRegistrationNumber, idh.IncomeLevel, idh.GrossAnnualIncome
from MST_FarmerProfile as fp inner join PersonalDetailsHistories as pdh on fp.personDetails_Id = pdh.PersonalDetails_Id
inner join ContactDetailsHistories as cdh on fp.contactDetails_Id = cdh.ContactDetails_Id
inner join IdentityCertificateHistories as ich on fp.IdentityCertificate_Id = ich.IdentityCertificate_Id
inner join BankDetailsHistories as bdh on fp.BankDetails_Id = bdh.BankDetails_Id
left join PacInsuranceDataHistories as pidh on fp.PacsInsuranceData_Id = pidh.PacsInsuranceData_Id
left join IncomeDetailsHistories as idh on fp.IncomeDetails_Id = idh.IncomeDetails_Id
where URN_No in(
select distinct MST_FarmerProfile_URN_No from PersonalDetailsHistories where MST_FarmerProfile_URN_No in(
select URN_No from MST_FarmerProfile where (CreatedOn>=#fromDate and CreatedOn<= #toDate and Status='Active')))
)a where a.num=1

Use this linq query after getting result from sql. p.ID is be your desire distinct column name
List<Person> distinctRecords = YourResultList
.GroupBy(p => new { p.ID})
.Select(g => g.First())
.ToList();

Related

how to select specific columns from three different tables in Oracle SQL

I am trying to select values from three different tables.
When I select all columns it works well, but if I select specific column, the SQL Error [42000]: JDBC-8027:Column name is ambiguous. appear.
this is the query that selected all that works well
SELECT
*
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
and this is the error query
SELECT DISTINCT
x.POLICY_NO,
x.POLICY_TITLE,
policy_no_count ,
B.SMALL_CATEGORY_SID,
C.SMALL_CATEGORY_TITLE
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
I am trying to select if A.POLICY_NO values duplicate rows more than 18, want to change C.SMALL_CATEGORY_TITLE values to "ZZ" and also want to cahge B.SMALL_CATEGORY_SID values to null.
that is why make 2 select in query like this
SELECT DISTINCT
x.POLICY_NO,
CASE WHEN (policy_no_count > 17) THEN 'ZZ' ELSE C.SMALL_CATEGORY_TITLE END AS C.SMALL_CATEGORY_TITLE,
CASE WHEN (policy_no_count > 17) THEN NULL ELSE B.SMALL_CATEGORY_SID END AS B.SMALL_CATEGORY_SID,
x.POLICY_TITLE
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
If i use that query, I got SQL Error [42000]: JDBC-8006:Missing FROM keyword. ¶at line 3, column 80 of null error..
I know I should solve it step by step. Is there any way to select specific columns?
That's most probably because of SELECT x.*, B.*,C.* - avoid asterisks - explicitly name all columns you need, and then pay attention to possible duplicate column names; if you have them, use column aliases.
For example, if that select (which is in a subquery) evaluates to
select x.id, x.name, b.id, b.name
then outer query doesn't know which id you want as two columns are named id (and also two names), so you'd have to
select x.id as x_id,
x.name as x_name,
b.id as b_id,
b.name as b_name
from ...
and - in outer query - select not just id, but e.g. x_id.

How can we use partition in Oracle query

I have query in which i used partition of avoid the duplicate value for particular column , but still it is giving duplicate row below i am mention my query in which i used partition
SELECT iol.M_product_id as faultyProduct , iol.SERIALNO,iol.M_product_id as newproduct, ma.Description,
mp.M_Product_category_id ,mi.issotrx, co.C_BPartner_ID,
ROW_NUMBER() OVER(PARTITION BY ma.Description ORDER BY iol.M_product_id DESC) rn
FROM M_inoutline iol
inner join M_inout mi ON (iol.m_inout_id = mi.m_inout_id)
inner join C_Order co ON (co.c_order_id = mi.c_order_id )
inner Join M_AttributeSetInstance ma ON (ma.m_attributesetinstance_id =iol.m_attributesetinstance_id)
inner join M_Product mp ON (mp.m_product_id = iol.m_product_id)
where mp.m_product_category_id= 1000447 AND mi.issotrx = 'Y';
Please help me out
For me it looks you want to do:
select * from (/*YOUR QUERY*/) where rn = 1;

How to left join with conditions in Toad Data Point Query Builder?

I'm trying to build a query in Toad Data Point. I have a subquery that has a row number to identify the records I'm interested in. This subquery needs to be left joined onto the main table only when the row number is 1. Here's the query I'm trying to visualize:
SELECT distinct E.EMPLID, E.ACAD_CAREER
FROM PS_STDNT_ENRL E
LEFT JOIN (
SELECT ACAD_CAREER, ROW_NUMBER() OVER (PARTITION BY ACAD_CAREER ORDER BY EFFDT DESC) as RN
FROM PS_ACAD_CAR_TBL
) T on T.ACAD_CAREER = E.ACAD_CAREER and RN = 1
When I try to replicate this, the row number condition is placed in the global WHERE clause. This is not the intended functionality because it removes any records that don't have a match in the subquery effectively making it an inner join.
Here is the query it's generating:
SELECT DISTINCT E.EMPLID, E.ACAD_CAREER, T.RN
FROM SYSADM.PS_STDNT_ENRL E
LEFT OUTER JOIN
(SELECT PS_ACAD_CAR_TBL.ACAD_CAREER,
ROW_NUMBER ()
OVER (PARTITION BY ACAD_CAREER ORDER BY EFFDT DESC)
AS RN
FROM SYSADM.PS_ACAD_CAR_TBL PS_ACAD_CAR_TBL) T
ON (E.ACAD_CAREER = T.ACAD_CAREER)
WHERE (T.RN = 1)
Is there a way to get the query builder to place that row number condition on the left join instead of the global WHERE clause?
I found a way to get this to work.
Add a calculated field to the main table with a value of 1.
Join the row number to this new calculated field.
Now the query has the filter in the join condition instead of the WHERE clause so that it joins as intended. Here is the query it made:
SELECT DISTINCT E.EMPLID, E.ACAD_CAREER, T.RN
FROM SYSADM.PS_STDNT_ENRL E
LEFT OUTER JOIN
(SELECT PS_ACAD_CAR_TBL.ACAD_CAREER,
ROW_NUMBER ()
OVER (PARTITION BY ACAD_CAREER ORDER BY EFFDT DESC)
AS RN
FROM SYSADM.PS_ACAD_CAR_TBL PS_ACAD_CAR_TBL) T
ON (E.ACAD_CAREER = T.ACAD_CAREER) AND (1 = T.RN)

How to select values from row with maximum date for multiple id matches

I'm not sure my title makes the question I am asking very clear. I am using an SQL Developer to query an Oracle database. I have contructed the query below which is able to pull the values I require for one specific ID. I need a query that will pull the same values but for multiple ids. I will need to run the same query on a monthly basis for a varying set of 20-50 ids. The database contains 80,000+ ids so I do not want to pull everything if I can avoid it. Is this possible?
SELECT b.id, a.final_grade, a.final_score
FROM db.table1 a, db.table2 b
where a.survey_id=b.survey_id
and b.id = '1796'
and a.created_dt = (select max (a.created_dt) from db.table1 a, db.table2 b
where a.survey_id=b.survey_id and b.cp_id = '1796')
thanks a lot for your help
Easiest way is to use ROW_NUMBER() and a WITH clause.
with data as
SELECT
b.id,
a.final_grade,
a.final_score,
ROW_NUMBER OVER (PARTITION BY b.id, order by a.created_dt desc) rn
FROM
db.table1 a
INNER JOIN db.table2 b
ON a.survey_id=b.survey_id
where
b.id in (<Comma seperated list of ids>)
)
SELECT * FROM DATA WHERE rn = 1
Note: if there are ties for created_dt for a given id an arbitrary row will be selected. If you instead want ties to be displayed replace ROW_NUMBER with RANK()
I think that this is what your looking for or at least this is what i got with your explanation:
SELECT b.id, a.final_grade, a.final_score
FROM db.table1 a, db.table2 b
where a.survey_id=b.survey_id
and b.id IN (<SELECT query with your list of ids>)
and a.created_dt **IN** (select max (a.created_dt) from db.table1 a, db.table2 b
where a.survey_id=b.survey_id and b.cp_id = b.id )
SELECT b.id, a.final_grade, a.final_score
FROM db.table1 a, db.table2 outerb
where a.survey_id=outerb.survey_id
and outerb.id IN (<SELECT query with your list of ids>)
and a.created_dt = (select max (a.created_dt) from db.table1 a, db.table2 b
where a.survey_id=b.survey_id and b.cp_id = outerb.id )
Is that what you are looking for? Question is not clear!

Using Linq to select a table based on inner join of top 5 from another table

I am trying to select a table from my database based on top 5 values from another table and met a roadblock.
here is the version without the top 5 values :
from d in Deals
from f in FacebookUserCategories
from s in SubCategories
where s.FacebookCategoryId == f.FacebookCategoryId
&& f.FacebookUserId == 1437585390
orderby f.Count descending
select d
However , what i need is to select Deals based on the top 5 Ids from SubCategories table, meaning i have to use a Take operator.
The below linq will help me achieve this :
(from f in FacebookUserCategories
from s in SubCategories
where s.FacebookCategoryId == f.FacebookCategoryId
orderby f.Count descending
select s.Id).Take(5)
Is there anyway for me to select the Deals table which has a SubCategoryId as a join from here?
Just to recap...i could write the sql.. it would be like this :
SELECT t1.* FROM Deal t1
INNER JOIN (
SELECT TOP 5 t2.Id FROM FacebookUserCategory , SubCategory t2
WHERE FacebookUserId = '1437585390'
AND FacebookUserCategory.FacebookCategoryId = t2.FacebookCategoryId
ORDER BY Count DESC) tbl
ON t1.SubCategoryId = tbl.Id
Try this, Use Join for all 3 tables, You use Join for only 2 tables, why not use Join for 3rd table also.
var result = from d in deals
let top5Counts =
(from f in FacebookUserCategories
join s in SubCategories on f.FacebookCategoryId equals s.FacebookCategoryId
where f.FacebookUserId == 1437585390
orderby f.Count descending
select s.Id).Take(5)
where top5Counts.Contains(d.SubCategoryId.Value)
select d;

Resources