I'm trying to perform an sql query as so:
select * from conversations where (user_1 = user_1_id and user_2 = user_2_id ) or (user_1 = user_2_id and user_2 = user_1_id )
I'm writing it in Ebean as so:
Conversation conversation = Ebean.find(Conversation.class)
.where()
.and(Expr.eq("user_1", user_1_id), Expr.eq("user_2", user_2_id))
.or(Expr.eq("user_1", user_2_id), Expr.eq("user_2", user_1_id))
.findUnique();
However this gives the following query:
select * from conversation where (user_1 = user_1_id and user_2 = user_2_id ) and (user_1 = user_2_id or user_2 = user_1_id )
I've been looking at the documentation, but I'm not getting a clear idea about how to refine the query to match my needs.
Can anyone help?
Have a look at the JavaDoc (it has an or expression as an example):
// Example: Using an Expr.or() method
Query<Order> query = Ebean.createQuery(Order.class);
query.where(
Expr.or(Expr.eq("status", Order.NEW),
Expr.gt("orderDate", lastWeek));
List<Order> list = query.findList();
This perhaps makes it a bit easier to understand why this code:
.or(Expr.eq("user_1", user_2_id), Expr.eq("user_2", user_1_id))
Results in:
(user_1 = user_2_id or user_2 = user_1_id )
You are, so to speak, using the or expression inside your second condition, instead of between the two conditions.
You need to put the or method first:
Conversation conversation = Ebean.find(Conversation.class)
.where().or(
Expr.and(Expr.eq("user_1", user_1_id), Expr.eq("user_2", user_2_id)),
Expr.and(Expr.eq("user_1", user_2_id), Expr.eq("user_2", user_1_id)))
.findUnique();
This should put the or between your paranthesises, and an and condition inside them.
Related
I have a query for Oracle database, built with CriteriaBuilder of Hibernate. Now, it has a IN clause which already takes about 800+ params.
Team says this may surpass 1000 and hitting the hard upper limit of Oracle itself, which only allows 1000 param for an IN clause. We need to optimize that.
select ih from ItemHistory as ih
where ih.number=:param0
and
ih.companyId in (
select c.id from Company as c
where (
( c.organizationId in (:param1) )
or
( c.organizationId like :param2 )
) and (
c.organizationId in (:param3, :param4, :param5, :param6, :param7, :param8, :param9, :param10, ..... :param818)
)
)
order by ih.eventDate desc
So, two solutions I can think of:
The easy one, as now the list from :param3 to :param818 are below 1000, and in the future, we may hit 1000, we can separate the list if size > 1000, into another IN clause, so it becomes:
c.organizationId in (:param3, :param4, :param5, :param6, :param7, :param8, :param9, :param10, ..... :param1002) or c.organizationId in (:param1003, ...)
Both the original code and solution 1 are not very efficient already. Although it can fetch 40K records in 25 seconds, we should use a GTT(Global Temporary Table), as per what I can find on AskTom or other sites, by professional DBAs. But I can only find SQL examples, not Java code.
What I can imagine is:
createNativeQuery("create global temporary table GTT_COMPANIES if not exist (companyId varchar(32)) ON COMMIT DELETE ROWS;"); and execute(Do we need index here?)
createNativeQuery("insert into GTT_COMPANIES (list)"); query.bind("1", query.getCompanyIds()); and execute(can we bind a list and insert it?)
use CriteriaQuery to select from this table(but I doubt, as CriteriaQueryBuilder will require type safe meta model class to be generated beforehand, and here we don't have the entity; this is an ad-hoc table and no model entity is mapped to it)
and, do we need to create GTT even the list size is < 1000? As often it is big, 700~800.
So, any suggestion? Someone got a working example of Hibernate CriteriaQuery + Oracle GTT?
The whole method is like this:
public List<ItemHistory> findByIdTypePermissionAndOrganizationIds(final Query<String> query, final ItemIdType idType) throws DataLookupException {
String id = query.getObjectId();
String type = idType.name();
Set<String> companyIds = query.getCompanyIds();
Set<String> allowedOrgIds = query.getAllowedOrganizationIds();
Set<String> excludedOrgIds = query.getExcludedOrganizationIds();
// if no orgs are allowed, we should return empty list
if (CollectionUtils.isEmpty(allowedOrgIds)) {
return Collections.emptyList();
}
try {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<ItemHistory> criteriaQuery = builder.createQuery(ItemHistory.class);
Subquery<String> subQueryCompanyIds = filterByPermissionAndOrgIdsInSubquery(query, builder, criteriaQuery);
Subquery<String> subQueryCompanyIds = criteriaQuery.subquery(String.class);
Root<Company> companies = subQueryCompanyIds.from(Company.class);
companies.alias(COMPANY_ALIAS);
Path<String> orgIdColumn = companies.get(Company_.organizationId);
/* 1. get permission based restrictions */
// select COMPANY_ID where (ORG_ID in ... or like ...) and (ORG_ID not in ... and not like ...)
// actually query.getExcludedOrganizationIds() can also be very long list(1000+), but let's do it later
Predicate permissionPredicate = getCompanyIdRangeByPermission(
builder, query.getAllowedOrganizationIds(), query.getExcludedOrganizationIds(), orgIdColumn
);
/* 2. get org id based restrictions, which was done on top of permission restrictions */
// ... and where (ORG_ID in ... or like ...)
// process companyIds with and without "*" by adding different predicates, like (xxx%, yyy%) vs in (xxx, yyy)
// here, query.getCompanyIds() could be very long, may be 1000+
Predicate orgIdPredicate = groupByWildcardsAndCombine(builder, query.getCompanyIds(), orgIdColumn, false);
/* 3. Join two predicates with AND, because originally filtering is done twice, 2nd is done on basis of 1st */
Predicate subqueryWhere = CriteriaQueryUtils.joinWith(builder, true, permissionPredicate, orgIdPredicate); // join predicates with AND
subQueryCompanyIds.select(companies.get(Company_.id)); // id -> COMPANY_ID
if (subqueryWhere != null) {
subQueryCompanyIds.where(subqueryWhere);
} else {
LOGGER.warn("Cannot build subquery of org id and permission. " +
"Org ids: {}, allowed companies: {}, excluded companies: {}",
query.getCompanyIds(), query.getAllowedOrganizationIds(), query.getExcludedOrganizationIds());
}
Root<ItemHistory> itemHistory = criteriaQuery.from(ItemHistory.class);
itemHistory.alias(ITEM_HISTORY_ALIAS);
criteriaQuery.select(itemHistory)
.where(builder.and(
builder.equal(getColumnByIdType(itemHistory, idType), id),
builder.in(itemHistory.get(ItemHistory_.companyId)).value(subQueryCompanyIds)
))
.orderBy(builder.desc(itemHistory.get(ItemHistory_.eventDate)));
TypedQuery<ItemHistory> finalQuery = entityManager.createQuery(criteriaQuery);
LOGGER.trace(LOG_MESSAGE_FINAL_QUERY, finalQuery.unwrap(org.hibernate.Query.class).getQueryString());
return finalQuery.setMaxResults(MAX_LIST_FETCH_SIZE).getResultList();
} catch (NoResultException e) {
LOGGER.info("No item history events found by permission and org ids with {}={}", type, id);
throw new DataLookupException(ErrorCode.DATA_LOOKUP_NO_RESULT);
} catch (Exception e) {
LOGGER.error("Error when fetching item history events by permission and org ids with {}={}", type, id, e);
throw new DataLookupException(ErrorCode.DATA_LOOKUP_ERROR,
"Error when fetching item history events by permission and org ids with " + type + "=" + id);
}
}
I know there are some answers to this error. I know it's a syntax error, but can't fix it!!
I'm running these commands in a Pentaho transformation. They are from one DB to another.
SELECT emp, codlug, nombre, pais, pcia, codp FROM CONDOR.TCODLUG
order by codlug desc
select *
FROM CONDOR.TCABTRAN o138195,
CONDOR.TCRES o138205,
CONDOR.TCCTES o138234,
CONDOR.TITEMS o138320,
CONDOR.TPDC o138351,
CONDOR.TPROV o138355,
CONDORBI.VRENTRAN o138514,
CONDOR.TROCCONT o138537
WHERE ( (o138195.EMP = o138514.EMP AND o138195.CODTRAN = o138514.CODTRAN AND o138195.NUMTRAN = o138514.NUMTRAN)
and (o138205.EMP(+) = o138514.EMP AND o138205.UNORG1(+) = o138514.UNORG1 AND o138205.UNORG2(+) = o138514.UNORG2 AND o138205.UNORG3(+) = o138514.UNORG3)
and (o138234.EMP(+) = o138514.EMP AND o138234.CODCC(+) = o138514.CODCC AND o138234.NUMCC(+) = o138514.NUMCC)
and (o138320.CODITEM(+) = o138537.CODITEM)
and (o138351.CTACONT = o138514.CTACONT)
and (o138355.EMP(+) = o138537.EMP AND o138355.NUMPROV(+) = o138537.NUMPROV)
and (o138537.EMP(+) = o138514.EMP AND o138537.CODTRAN(+) = o138514.CODTRAN AND o138537.NUMTRAN(+) = o138514.NUMTRAN AND o138537.RENGLON(+) = o138514.RENGLON))
AND ((DECODE(o138351.ACRES,1,'C.Res',NULL)) = 'C.Res')
-- AND (o138514.CTACONT BETWEEN :"Cuenta Desde" AND :"Cuenta Hasta")
-- AND (o138514.FECREG BETWEEN :"Desde" AND :"Hasta")
-- AND (o138514.EMP = :"Empresa")
When I run the transformation it throws the syntax error:
java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended
i´ve already search but can´t find a proper answer.
THNAKS!!!
You can have only one statement in the input table.
Well, you can have more, provided that they are separated by ";". However only the last one will produce rows in the output. (This feature is there to make temporary tables or procedures to execute on the last statement).
If you want a union, and do not want to do it in sql, then make two table input steps and drop those two in the same PDI step. You'll get an error if the metadata (column names, order and types) are not the same.
I have a scenario where there are two sheets(csv). Created two tables for it.
When there s a good data I could map it with a value( id statistic value) from the second table. If I have bad data I should map it with id statistic value again (but a different value). however, I'm unable to use not exists in spark SQL. And I get the error below:
mismatched input 'from' expecting {, 'WHERE', 'GROUP', 'ORDER', 'HAVING', 'LIMIT', 'LATERAL', 'WINDOW', 'UNION', 'EXCEPT', 'INTERSECT', 'SORT', 'CLUSTER', 'DISTRIBUTE'}(line 1, pos 386)
at org.apache.spark.sql.catalyst.parser.ParseException.withCommand(ParseDriver.scala:197)
at org.apache.spark.sql.catalyst.parser.AbstractSqlParser.parse(ParseDriver.scala:99)
at org.apache.spark.sql.execution.SparkSqlParser.parse(SparkSqlParser.scala:45)
CODE:
select
a.ptf_id,a.ptf_code,a.share_id,a.share_code,a.bench_id,a.bench_code
, a.l1_calculation_date,a.l1_begin_date,a.l1_end_date,a.l1_running_date
, a.l1_frequency,a.l1_calculation_step,a.l1_performance_currency
, a.l1_configuration,a.l1_valuation_source,a.l1_nav_valuation_type
, a.l1_setting_reference_type, a.l1_setting_valuation_type
, a.l1_sharpe_ratio_annualized as value,b.id_statistic
from
parquetFile a,
pairRDD b,
stats c
where
a.l1_nav_valuation_type= b.l1_nav_valuation_type
and a.l1_valuation_source = b.l1_valuation_source
and b.l1_Perf = 'l1_sharpe_ratio_annualized'
OR (a.ptf_id not EXISTS (
select e.ptf_id from pairRDD d, parquetFile e
where d.l1_valuation_source = e.l1_valuation_source
AND d.l1_nav_valuation_type = e.l1_nav_valuation_type)
and b.l1_valuation_source ='')
this query works in SQL if I use "NOT in"
please help me on what other options to use in this scenario other than not exists.
The query is a bit hard to follow as written. It's not clear (to me anyway) what your intentions are for the stats table since you don't select anything from it so I removed it. Obviously I haven't tried this myself but at a glance, you might try something like this instead:
select
a.PTF_ID,
a.PTF_CODE,
a.SHARE_ID,
a.SHARE_CODE,
a.BENCH_ID,
a.BENCH_CODE,
a.L1_CALCULATION_DATE,
a.L1_BEGIN_DATE,
a.L1_END_DATE,
a.L1_RUNNING_DATE,
a.L1_FREQUENCY,
a.L1_CALCULATION_STEP,
a.L1_PERFORMANCE_CURRENCY,
a.L1_CONFIGURATION,
a.L1_VALUATION_SOURCE,
a.L1_NAV_VALUATION_TYPE,
a.L1_SETTING_REFERENCE_TYPE,
a.L1_SETTING_VALUATION_TYPE,
a.L1_SHARPE_RATIO_ANNUALIZED as VALUE,
b.ID_STATISTIC
from
PARQUETFILE a
inner join
PAIRRDD b
on
a.L1_NAV_VALUATION_TYPE = b.L1_NAV_VALUATION_TYPE and
a.L1_VALUATION_SOURCE = b.L1_VALUATION_SOURCE
left outer join (
select
e.PTF_ID
from
PAIRRDD d
inner join
PARQUETFILE e
on
d.L1_VALUATION_SOURCE = e.L1_VALUATION_SOURCE AND
d.L1_NAV_VALUATION_TYPE = e.L1_NAV_VALUATION_TYPE
where
b.L1_VALUATION_SOURCE = ''
) x
on
a.PTF_ID = x.PTF_ID
where
b.L1_PERF = 'l1_sharpe_ratio_annualized' or
x.PTF_ID is null
i am doing a task converting VB script written from Powerbuild to java,
i am struggled at converting the DataStore Object into java ,
i have something like this :
lds_appeal_application = Create DataStore
lds_appeal_application.DataObject = "ds_appeal_application_report"
lds_appeal_application.SetTransObject(SQLCA)
ll_row = lds_appeal_application.retrieve(as_ksdyh, adt_start_date, adt_end_date, as_exam_name, as_subject_code)
for ll_rc = 1 to ll_row
ldt_update_date = lds_appeal_application.GetItemDatetime(ll_rc, "sqsj")
ls_caseno = trim(lds_appeal_application.GetItemString(ll_rc, "caseno"))
ls_candidate_no = trim(lds_appeal_application.GetItemString(ll_rc, "zkzh"))
ls_subjectcode = trim(lds_appeal_application.GetItemString(ll_rc, "kmcode"))
ls_papercode = trim(lds_appeal_application.GetItemString(ll_rc, "papercode"))
ls_name = trim(lds_appeal_application.GetItemString(ll_rc, "mc"))
ll_ksh = lds_appeal_application.GetItemDecimal(ll_rc, "ks_h")
ll_kmh = lds_appeal_application.GetItemDecimal(ll_rc, "km_h")
simply speaking, a datasoure is created and a data table is point to it by sql query(ds_appeal_application_report). Finally using a for loop to retrieve information from the table.
in java way of doing, i use an entities manager to createnativequery and the query can result a list of object array. However, i just dont know how to retrieve the information like VB using the DataStore Object.
please give me some advice . Thanks
Hi guys i have a question regarding this annoying error. Below it's my code
String updateDefaultBU = "update ClientUserVO set defaultBUnit = :yes where id = (select max(cu1.id) from ClientUserVO cu1 where cu1.user.id = :userId and cu1.defaultBUnit = :no)";
updateDefaultBU = " and not exists (select cu2.id from ClientUserVO cu2 where cu2.user.id = :userId and cu2.defaultBUnit = :yes) ";
Query updateQuery = session.createQuery(updateDefaultBU);
updateQuery.setString("yes", "Y");
updateQuery.setString("no", "N");
updateQuery.setLong("userId", userID);
I don't seem to understand where does it find a not that could not be traversed, also this error is very general and it could happen for various reasons, could you tell me what i am doing wrong?
Thanks
In your second assignment of updateDefaultBU you are changing the content of the variable completely and not concatenating with the first assignment (as I assume you want to do).
It is possible that you get the error because you run updateQuery.setString("no", "N") but the second assignment has no :no value in it.
Try changing the second line to updateDefaultBU.concat(" <your string> ")
Also have you tried to debug to see exactly where the error is happening?