Criteria to apply Restrictions and Projection then count distinct results - linq

I'm trying to perform the following functionality using Criteria, but it's giving me a Run-time error indicating an error in SQL.
var query = session.CreateCriteria<TableName>()
.Add(Restrictions.Disjunction()
.Add(Restrictions.InsensitiveLike("Property1", keyword, MatchMode.Anywhere))
.Add(Restrictions.InsensitiveLike("Property2", keyword, MatchMode.Anywhere)));
query.SetProjection(Projections.Count(Projections.Distinct(
Projections.ProjectionList()
.Add(Projections.Property("Property1"))
.Add(Projections.Property("Property3"))
)));
The table mapping looks like this:
public class TableName
{
public int Property1 {get;set;}
public int Property2 {get;set;}
public int Property3 {get;set;}
public int Property4 {get;set;}
}
I need to count Distinct Results Based on my Projections, I don't want to count the results as a whole row!
Can anyone please help me with this?
----------UPDATE----------
This what I'm trying to accomplish:
select Count(*)
from
(
select distinct Property1 , Property2
from tableName
where Property1 like '%t%' or Property3 like '%t%'
) As x

Your criteria, if they could ever be translated, would result in an SQL like:
SELECT count(DISTINCT Property1, Property3)
FROM TableName
WHERE Property1 LIKE '%keyword%' OR Property2 LIKE '%keyword%'
which would not work. Use
Projections.RowCount() or Projections.RowCountInt64()
for a COUNT(*) equivalent.
Possibly, a GROUP BY clause makes sense (instead of DISTINCT). (I hope you don't need an Int64 result count when searching with LIKE '%keyword%'! ;-)

Related

jdbctemplate equivalent of following query

I have a long list of argument which I need to send to oracle database. I was able to do it by splitting the query but I am unable to find a way to do similar using jdbcTemplate. my query is:
select name,age from person where personId in (A1,F2,D3...G900)
or personId in (A901, C902 , ... R1800)
or personId in (A1801,G1802 .... H2700)
or personId in (P2701, G2702 ... R3600)
or since oracle allow more than 1000 touple but does not allow in so JDBC equivalent for
SELECT field1, field2, field3
FROM table1
WHERE (1, name) IN ((1, value1), (1, value2), (1, value3),.....(1, value5000));
List<Map<String, Object>> findPeeps(List<Long> personIds) {
String sql = "select name,age from person where personId in (:personIds)";
return namedParameterJdbcTemplate.queryForList(sql, new MapSqlParameterSource("personIds", personIds));
}
As #zaki said you can use that but the error that you are getting is from Oracle since there is limit of records you can put in WHERE IN clause. You can try something like this
insert into TEMP values ( ... );
select * from T where (a,b) in (select x,y from temp);
delete from TEMP;

Select multiple fields using findByField in JPA

I am trying to select mulitple values from a table where input can be any of the 5 columns of the table or a combination of those fields.
In order to use findByField in JPA I have to many combinations of findByField and call them selectively by checking which field is blanks.
Is there an easier solution to this?
I have 5 columns in a table that I would like to query on.
If user enters all 5 then i want to select using all 5 fields like below.
select * from table where field1 = :field1 and field2 = :field2 and field3 = :field3 and field4 = :field4 and field5 = :field5;
But if user enters only 2 fields, then I just want to query on those 2 fields like this.
select * from table where field3 = :field3 and field5 = :field5.
In JPA we can do findByField1AndField2AndField3
But i am having for 5 different input possibilities i will have to create like 120 possibilities.
So is there any simpler solution?
Thank you!
It seems there is no automatic generator to build all possible combinations of JPA queries, but you should use the power of JPA dynamic queries like this :
Build predicates for all the fields and apply them on the basis of user input.
public List<Employee> findByCriteria(String employeeName){
return employeeDAO.findAll(new Specification<Employee>() {
#Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if(employeeName!=null) {
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("employeeName"), employeeName)));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}
Helpful Link: https://javadeveloperzone.com/spring/spring-jpa-dynamic-query-example/
You can use a custom #Query in your #Repository interface and add as many params as you need.
#Query(value="SELECT *
FROM table
WHERE (:field1 IS NULL
OR field1 = :field1)
AND (:field2 IS NULL
OR field2 = :field2)",
nativeQuery=true)
public Table findMatchingTable(#Param("field1") String field1, #Param("field2") String field2)

Apache PIG - GROUP BY

I am looking to achieve the below functionality in Pig. I have a set of sample records like this.
Note that the EffectiveDate column is sometimes blank and also different for the same CustomerID.
Now, as output, I want one record per CustomerID where the EffectiveDate is the MAX. So, for the above example, i want the records highlighted as shown below.
The way I am doing it currently using PIG is this:
customerdata = LOAD 'customerdata' AS (CustomerID:chararray, CustomerName:chararray, Age:int, Gender:chararray, EffectiveDate:chararray);
--Group customer data by CustomerID
customerdata_grpd = GROUP customerdata BY CustomerID;
--From the grouped data, generate one record per CustomerID that has the maximum EffectiveDate.
customerdata_maxdate = FOREACH customerdata_grpd GENERATE group as CustID, MAX(customerdata.EffectiveDate) as MaxDate;
--Join the above with the original data so that we get the other details like CustomerName, Age etc.
joinwithoriginal = JOIN customerdata by (CustomerID, EffectiveDate), customerdata_maxdate by (CustID, MaxDate);
finaloutput = FOREACH joinwithoriginal GENERATE customerdata::CustomerID as CustomerID, CustomerName as CustomerName, Age as Age, Gender as gender, EffectiveDate as EffectiveDate;
I am basically grouping the original data to find the record with the maximum EffectiveDate. Then I join these 'grouped' records with the Original dataset again to get that same record with Max Effective date, but this time I will also get additional data like CustomerName, Age and Gender. This dataset is huge, so this approach is taking a lot of time. Is there a better approach?
Input :
1,John,28,M,1-Jan-15
1,John,28,M,1-Feb-15
1,John,28,M,
1,John,28,M,1-Mar-14
2,Jane,25,F,5-Mar-14
2,Jane,25,F,5-Jun-15
2,Jane,25,F,3-Feb-14
Pig Script :
customer_data = LOAD 'customer_data.csv' USING PigStorage(',') AS (id:int,name:chararray,age:int,gender:chararray,effective_date:chararray);
customer_data_fmt = FOREACH customer_data GENERATE id..gender,ToDate(effective_date,'dd-MMM-yy') AS date, effective_date;
customer_data_grp_id = GROUP customer_data_fmt BY id;
req_data = FOREACH customer_data_grp_id {
customer_data_ordered = ORDER customer_data_fmt BY date DESC;
req_customer_data = LIMIT customer_data_ordered 1;
GENERATE FLATTEN(req_customer_data.id) AS id,
FLATTEN(req_customer_data.name) AS name,
FLATTEN(req_customer_data.gender) AS gender,
FLATTEN(req_customer_data.effective_date) AS effective_date;
};
Output :
(1,John,M,1-Feb-15)
(2,Jane,F,5-Jun-15)

MVC3 select int value through LINQ

I am trying to get customerId from Customer table.
However, when I try to make it, it has error said, 'Cannot implicitly convert type 'System.Linq.Iqueryable' to 'int''
How can I get customerId??
Thank you.
Here is my coding.
int customerId = from a in db.Customer
where a.userName == customerName
select a.customerId;
//it has error in here.
order.customerId = customerId;
It's possible that your query could return multiple rows. You need to tell LINQ that you only want the first (or a single) result:
int customerId = (from a in db.Customer
where a.userName == customerName
select a.customerId).First();
I like using the .Single() function when I know there should be only one row.
int customerId = (from a in db.Customer
where a.userName == customerName
select a.customerId).Single();
This throws an exception if more or less than one row is found, which is sometimes useful depending on your situation.
use it this way:
var customer = db.Customer.FirstOrDefault(c =>c.userName == customerName)
var id = customer.Id
Select returns an IEnumerable, so you can't convert it to int.
There is one more suggestion I can recommend for this question is to use First or default.
var customerId = (from a in db.Customer
where a.userName == customerName
select a.customerId).FirstOrDefault();
order.customerId = customerId; this should now work fine since it already knows it int

LINQ to Entities - DISTINCT on one column

Is there a way to write following query with Linq to Entities (or Entity SQL, or Method Syntax, or any other way, but I would like to achieve it with Linq to Entities):
SELECT DISTINCT Column1
FROM Table1
I'm using Entity Framework 4. Of course I don't want to use Distinct method that filters data after data is fetched from database.
thanks,Pawel
Use something like
db.Table1.Select(t => t.Column1).Distinct()
As Munim mentioned in his comment, the Distinct() method does add the DISTINCT to the query. So resulting SQL query will be
SELECT [Distinct1].[Column1] AS [Column1]
FROM ( SELECT DISTINCT
[Extent1].[Column1] AS [Column1]
FROM [dbo].[Table1] AS [Extent1]
) AS [Distinct1]
For distinct by column, use this extension:
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
{
return items.GroupBy(property).Select(x => x.First());
}

Resources