Same property ie used twice in 'In condition' generate wrong SQL - sql

from CardAssignInfo a left join a.card.detailSet d
where d.category.system.systemId = :systemId and a.personId is not null
and (a.state.id in (:destroyStateIds) or (a.state.id in (:returnStateIds) and d.category.reuseable = true))
this HQL will generate SQL somewhat like:
........... something.stateId in () or (something.stateId in (:destroyStateIds, :returnStateIds) and ......)
The parameter are injected into the same place of SQL in condition, left another place with null condition.
I wonder is it hibernate's specification to have this behavior?

Related

Set a Variable in a case expression

I am looking to pass declared variables to build my string. I think I want to set my variable via a case expression but I have not done this before. Here is what I have done thus far.
DECLARE #stu_conv AS VARCHAR(5)
-- I think I need a select here.
set #stu_conv = CASE WHEN ITMMASTER.STU_0 ='KG' THEN'2.2'END
SELECT
YPRIMAT.YCROPYR_0
,ITMMASTER.TCLCOD_0
,SPRICLIST.DCGVAL_3
,ITMMASTER.TSICOD_2
,ITMMASTER.ACCCOD_0
,(BASPRI_0*#stu_conv) AS ImportstringAS Importstring
FROM LIVE.YPRIMAT
INNER JOIN LIVE.ITMMASTER ON YPRIMAT.ITMREF_0 = ITMMASTER.ITMREF_0
LEFT OUTER JOIN LIVE.SPRICLIST ON ITMMASTER.TCLCOD_0 = SPRICLIST.PLICRI1_0
WHERE SPRICLIST.PLICRD_0 = 'SPL000020'
I don't see the point for using a variable here, and trying to set it outside the query does not make sense, since you most likely want the value to reset for each row.
I would suggest moving the case expression into the query, as follows:
select
y.ycropyr_0,
i.tclcod_0,
s.dcgval_3,
i.tsicod_2,
i.acccod_0,
baspri_0 * case when i.stu_0 = 'KG' then 2.2 else 1 end as importstringas importstring
from live.yprimat y
inner join live.itmmaster i on y.itmref_0 = i.itmref_0
left outer join live.spriclist s on i.tclcod_0 = s.plicri1_0
where s.plicrd_0 = 'SPL000020'
I assumed that you want a value of 1 when stu_0 is not 'KG', but you can change this as needed.
Side note:
I modified your query to use table aliases. This makes the query shorter to write and somehow easier to read
you would need to prefix column baspri_0 with the table it belongs to (as your query is, it is not possible to tell)
I'm not sure why you're declaring a string and then multiplying it, but I would just inline the case (and add a default case?):
,(BASPRI_0 * CASE
WHEN ITMMASTER.STU_0 ='KG'
THEN 2.2
ELSE ???
END) AS Importstring

PostgreSQL conditional where clause

In my Ruby on Rails app I'm using blazer(https://github.com/ankane/blazer) and I have the following sql query:
SELECT *
FROM survey_results sr
LEFT JOIN clients c ON c.id = sr.client_id
WHERE sr.client_id = {client_id}
This query works really well. But I need to add conditional logic to check if client_id variable is present. If yes then I filter by this variable, if not then I not launching this where clause. How can I do it in PostgreSQL?
Check if its null OR your condition like this:
WHERE {client_id} IS NULL OR sr.client_id = {client_id}
The WHERE clause evaluate as follow: If the variable is empty, then the WHERE clause evaluate to true, and therefore - no filter. If not, it continue to the next condition of the OR
If anyone faced with the psql operator does not exist: bigint = bytea issue, here is my workaround:
WHERE ({client_id} < 0 AND sr.client_id > {client_id}) OR sr.client_id = {client_id}
Please consider that, client_id generally cannot be negative so you can use that information for eleminating the operation cast issue.
My solution:
I use spring data jpa, native query.
Here is my repository interface signature.
#Query(... where (case when 0 in :itemIds then true else i.id in :itemIds end) ...)
List<Item> getItems(#Param("itemIds) List<Long> itemIds)
Prior calling this method, I check if itemIds is null. If yes, I set value to 0L:
if(itemIds == null) {
itemIds = new ArrayList<Long>();
itemIds.add(0L);
}
itemRepo.getItems(itemIds);
My IDs starts from 1 so there is no case when ID = 0.

In SQL , how do I JOIN a column that is usually null so that the data is still retrieved?

I want to incorporate a new column into a working SQL query.
However, it causes the whole query return nothing at all(because the column is mostly null in the database) .
Here's my pared-down code so far :
SELECT DISTINCT submittedRow.PERFORMED_DATE as "submitted",
supervisorRow.PERFORMED_DATE as "superv",
/* coalesce(sodRow.PERFORMED_DATE, TO_DATE('2000/07/07', 'YYYY/MM/DD') ) */ null AS "SOD"
hhs_umx_resp_activity submittedRow
join hhs_umx_resp_activity supervisorRow ON supervisorRow.reg_request_id = configRow.reg_request_id
/* join hhs_umx_resp_activity sodRow ON sodRow.reg_request_id = approvedRow.reg_request_id */
left join HHS_UMX_REG_REQUESTS hurr on hurr.reg_request_id = hur.reg_request_id
WHERE
and supervisorRow.ACTIVITY_RESULT_CODE = 'ASP'
AND submittedRow.activity_result_code = 'SBT'
/* AND sodRow.activity_result_code = 'ASD'*/
and hur.REG_REQUEST_ID IN ('262097')
The column that is mostly null, which I want to add in, is sodRow ( that's why the code AND sodRow.activity_result_code = 'ASD' is commented ).
Whenever I put back the extra join for sodRow , it just nulls out everything and I get no results at all. But I want it to work like a NVL or COALESCE, where it only displays that column if it exists, and otherwise just shows everything else.
I tried to create a view first in the code, then to do UNION on it. But it seems like view are only for PL/SQL code.
I also tried the outer joins, but this doesn't work.
I think the problem may be in the WHERE condition of my join code. I did like Dmitri suggest belwo :
AND nvl(sodRow.activity_result_code, 'ASD') = 'ASD'
AND nvl(configRow.activity_result_code, 'ACL') = 'ACL'
or also alternatively :
problem is that it won't return any rows. I.E If we're looking for 'ACL' then the previous check of 'ASD' becomes true and will render the next check useless.
I think I'm just having trouble visualizing how the joins work here
, thanks !
May be you can try left outer join
left outer join hhs_umx_resp_activity sodRow ON sodRow.reg_request_id = approvedRow.reg_request_id
and nvl
AND nvl(sodRow.activity_result_code, 'ASD') = 'ASD'
it will return records with null in sodRow.activity_result_code or 'ASD' in it

Handle null values within SQL IN clause

I have following sql query in my hbm file. The SCHEMA, A and B are schema and two tables.
select
*
from SCHEMA.A os
inner join SCHEMA.B o
on o.ORGANIZATION_ID = os.ORGANIZATION_ID
where
case
when (:pass = 'N' and os.ORG_ID in (:orgIdList)) then 1
when (:pass = 'Y') then 1
end = 1
and (os.ORG_SYNONYM like :orgSynonym or :orgSynonym is null)
This is a pretty simple query. I had to use the case - when to handle the null value of "orgIdList" parameter(when null is passed to sql IN it gives error). Below is the relevant java code which sets the parameter.
if (_orgSynonym.getOrgIdList().isEmpty()) {
query.setString("orgIdList", "pass");
query.setString("pass", "Y");
} else {
query.setString("pass", "N");
query.setParameterList("orgIdList", _orgSynonym.getOrgIdList());
}
This works and give me the expected output. But I would like to know if there is a better way to handle this situation(orgIdList sometimes become null).
There must be at least one element in the comma separated list that defines the set of values for the IN expression.
In other words, regardless of Hibernate's ability to parse the query and to pass an IN(), regardless of the support of this syntax by particular databases (PosgreSQL doesn't according to the Jira issue), Best practice is use a dynamic query here if you want your code to be portable (and I usually prefer to use the Criteria API for dynamic queries).
If not need some other work around like what you have done.
or wrap the list from custom list et.

SQL query with variable "Where"

I am new with SQL.
How can I write a query, where the Where condition be dependent on a statement which it will be given from a user?
I have this:
SELECT TablePersdaten.Vorname, TablePersdaten.Nachname, TableBezahlung.Datum, TableBezahlung.BelegNr, TableBezahlung.Betrag, Sum(TableBezahlung.Betrag) AS SummevonBetrag
FROM ((TableTeilnehmer INNER JOIN TablePersdaten ON TableTeilnehmer.IDPersdaten = TablePersdaten.IDPersdaten) INNER JOIN TableKurse ON TableTeilnehmer.IDKurs = TableKurse.IDKurs) INNER JOIN TableBezahlung ON TableTeilnehmer.IDTeilnehmer = TableBezahlung.IDStudent
WHERE TableBezahlung.Datum = "VALUE GIVEN FROM USER"
GROUP BY TablePersdaten.Vorname, TablePersdaten.Nachname, TableBezahlung.Datum, TableBezahlung.BelegNr, TableBezahlung.Betrag
ORDER BY TableBezahlung.Datum;
EDIT: I'm using Access 2013, but I'm coding everything myself with SQL-Code. The values should be given through a form.
Research stored procedures. You can include user input as a parameter and then pass it to a WHERE clause through a declared parameter.
So ideally it would go something like (and beware of the INT part it may have to have a different value that corresponds to table.datum:
CREATE PROCEDURE dbo.Proc1
#parameter1 INT
AS
BEGIN
SELECT TablePersdaten.Vorname, TablePersdaten.Nachname, TableBezahlung.Datum, TableBezahlung.BelegNr, TableBezahlung.Betrag, Sum(TableBezahlung.Betrag) AS SummevonBetrag
FROM ((TableTeilnehmer INNER JOIN TablePersdaten ON TableTeilnehmer.IDPersdaten = TablePersdaten.IDPersdaten) INNER JOIN TableKurse ON TableTeilnehmer.IDKurs = TableKurse.IDKurs) INNER JOIN TableBezahlung ON TableTeilnehmer.IDTeilnehmer = TableBezahlung.IDStudent
WHERE TableBezahlung.Datum = #parameter1
GROUP BY TablePersdaten.Vorname, TablePersdaten.Nachname, TableBezahlung.Datum, TableBezahlung.BelegNr, TableBezahlung.Betrag
ORDER BY TableBezahlung.Datum;
END
And of course execute the procedure after creation:
EXEC dbo.Proc1 '#parameter1value'
If you parameterize the input "VALUE GIVEN FROM USER" that might be what you're after.
...
WHERE TableBezahlung.Datum = &UserValue
...
The single '&' will substitute that value once. If you use '&&', it will substitute that value through the end of your session.