How to apply distinct to perticular column and fetch all values from table in JPA(Criteria Builder) - postgresql

I have written JPA query in that I want to apply distinct to only one column but here it is applying to all columns in table.
CriteriaBuilder cb = entityManager_gbl.getCriteriaBuilder();
CriteriaQuery<sourceTracking> cq = cb.createQuery(sourceTracking.class);
Root<sourceTracking> data1 = cq.from(sourceTracking.class);
Join<sourceTracking,status> joinobj=data1.join("sts");
Subquery<Number> subq=cq.subquery(Number.class);
Root<sourceTracking> sbf=subq.from(sourceTracking.class);
subq.select(cb.min(sbf.<Number>get("hopcount"))).groupBy(sbf.<String>get("message_id"));
cq.multiselect(cq.from(sourceTracking.class).get("message_id"));
cq.distinct(true);
cq.select(data1).orderBy(cb.asc(data1.get("message_id")));;
TypedQuery<sourceTracking> tquery = entityManager_gbl.createQuery(cq);
Here is my Hibernate query
select distinct sourcetrac0_.tablekey as tablekey1_2_, sourcetrac0_.alt_recipient_addr as alt_reci2_2_,
sourcetrac0_.alt_recipient_tried as alt_reci3_2_,sourcetrac0_.arrival_time as arrival_4_2_, sourcetrac0_.delivery_status as delivery5_2_, sourcetrac0_.dispatch_time as dispatch6_2_,
sourcetrac0_.hopcount as hopcount7_2_, sourcetrac0_.id as id8_2_, sourcetrac0_.id1 as id9_2_, sourcetrac0_.mail_orig_time as mail_or10_2_,
sourcetrac0_.mail_server as mail_se11_2_, sourcetrac0_.mailtype as mailtyp12_2_, sourcetrac0_.message_id as message13_2_, sourcetrac0_.nexthop as nexthop14_2_,
sourcetrac0_.precedence as precede15_2_, sourcetrac0_.receiver as receive16_2_, sourcetrac0_.securityclassification as securit17_2_, sourcetrac0_.sender as sender18_2_,
sourcetrac0_.subject as subject19_2_ from source_tracking sourcetrac0_ inner join status_table status2_ on sourcetrac0_.message_id=status2_.message_id
cross join source_tracking sourcetrac1_ order by sourcetrac0_.message_id asc,sourcetrac0_.hopcount asc.
I want to apply distinct to only one column here is what needed query
select distinct on(sourcetrac0_.message_id) sourcetrac0_.message_id,sourcetrac0_.tablekey as tablekey1_2_, sourcetrac0_.alt_recipient_addr as alt_reci2_2_,
sourcetrac0_.alt_recipient_tried as alt_reci3_2_,sourcetrac0_.arrival_time as arrival_4_2_, sourcetrac0_.delivery_status as delivery5_2_, sourcetrac0_.dispatch_time as dispatch6_2_,
sourcetrac0_.hopcount as hopcount7_2_, sourcetrac0_.id as id8_2_, sourcetrac0_.id1 as id9_2_, sourcetrac0_.mail_orig_time as mail_or10_2_,
sourcetrac0_.mail_server as mail_se11_2_, sourcetrac0_.mailtype as mailtyp12_2_, sourcetrac0_.message_id as message13_2_, sourcetrac0_.nexthop as nexthop14_2_,
sourcetrac0_.precedence as precede15_2_, sourcetrac0_.receiver as receive16_2_, sourcetrac0_.securityclassification as securit17_2_, sourcetrac0_.sender as sender18_2_,
sourcetrac0_.subject as subject19_2_ from source_tracking sourcetrac0_ inner join status_table status2_ on sourcetrac0_.message_id=status2_.message_id
cross join source_tracking sourcetrac1_ order by sourcetrac0_.message_id asc,sourcetrac0_.hopcount asc

That's no possible because DISTINCT is done on the result of the query. Read more here:
DISTINCT for only one Column

Related

Is there a way to modify this query and make it more simple?

I am working on a MySQl data base and have several tables that I need to join based on a temporary table that I created (layer_2).
Each table that I join has the join key for the next table;
E.g. layer_2 joins with "colegios" table, then the result will have the join key for the next table "ciudades". and finally the result will have the Join key for the next table "departamentos".
from what I got it works but I want to know if there is a way to simplify this?
Select
cuestionario_id,
tiempo,
nro_preguntas,
nro_preguntas_correctas,
tipo_usuario,
fecha_creacion_cuestionario,
con_tiempo,
det_cuestionarios_id,
respuesta_seleccionada,
pregunta_id,
enunciado,
respuesta_correcta,
usuarios_id,
dominio_correo,
tipo_institucion,
materia,
tematica,
area,
nombre_colegios,
direccion_colegios,
nombre_ciudades,
redsaber.departamentos.nombre as nombre_departamentos
From
(
Select
cuestionario_id,
tiempo,
nro_preguntas,
nro_preguntas_correctas,
cuestionable_id,
tipo_usuario,
fecha_creacion_cuestionario,
con_tiempo,
det_cuestionarios_id,
respuesta_seleccionada,
pregunta_id,
enunciado,
respuesta_correcta,
usuarios_id,
dominio_correo,
cole_ciud_id,
tipo_institucion,
materia,
tematica,
area,
combine_ciudad_id,
nombre_colegios,
direccion_colegios,
redsaber.ciudades.nombre as nombre_ciudades,
departamento_id
From
(Select
cuestionario_id,
tiempo,
nro_preguntas,
nro_preguntas_correctas,
cuestionable_id,
tipo_usuario,
fecha_creacion_cuestionario,
con_tiempo,
det_cuestionarios_id,
respuesta_seleccionada,
pregunta_id,
enunciado,
respuesta_correcta,
usuarios_id,
dominio_correo,
cole_ciud_id,
tipo_institucion,
materia,
tematica,
area,
ifnull(redsaber.colegios.ciudad_id,cole_ciud_id) as combine_ciudad_id,
redsaber.colegios.nombre as nombre_colegios,
redsaber.colegios.direccion as direccion_colegios
From layer_2
Left Join redsaber.colegios on layer_2.cole_ciud_id = redsaber.colegios.id
AND tipo_institucion = 'Colegio') as layer_3
Left Join redsaber.ciudades on combine_ciudad_id = redsaber.ciudades.id) as layer_4
Left Join redsaber.departamentos on departamento_id = redsaber.departamentos.id

Getting duplicate column ERROR while trying to insert same column with two different datatypes using SELECT INTO clause in PostgreSql

I need to insert createdate column twice with two different datatypes one with the datatype defined in the table itself and another in char datatype.
I can insert it by changing the alias name of createdate column but can't insert with same alias name which i need.
so help me out to get correct way of doing it.
My query:
SELECT DISTINCT TE.id, T.debatchqueuelink, TE.transactionlink,
EC.errorclassification, TE.errorvalue,
EC.errorparameter, TE.classificationlink, TE.description,
TE.createdate AS createdate, TO_CHAR(TE.createdate, 'MM/dd/yyyy') AS createdate,
TE.status, TE.rebutt, TE.rebuttedstatus, BQ.appbatchnumber,
BQ.scanbatchnumber, BQ.clientlink, BQ.locationlink, T.patientid,
(DEUD.firstname|| ' ' ||DEUD.lastname) AS deusername, DEUD.email AS deuseremail,
(QCUD.firstname|| ' ' ||QCUD.lastname) AS qcusername, TE.inactive,
TE.decomment
INTO table373
FROM qctransactionerror TE
INNER JOIN errorclassification EC ON EC.id = TE.classificationlink
INNER JOIN qctransaction T ON T.id = TE.transactionlink
INNER JOIN batchqueue BQ ON T.debatchqueuelink = BQ.id
INNER JOIN batchqueue QCBQ ON T.qcbatchqueuelink = QCBQ.id
INNER JOIN userdetail QCUD ON QCBQ.assignedto = QCUD.id
INNER JOIN userdetail DEUD ON BQ.assignedto = DEUD.id
WHERE TE.inactive='t'
AND TE.status IN ('ERROR','QCCORRECTED')
LIMIT 0
The actual error message I am getting is:
Duplicate column:column "createdate" specified more than once

Sybase SQL - Select Most recent record and line up with the values from previous record

I am trying the following query on data table listed below....Sybase does not allow row_number() function. Any suggestions would be very helpful:
select
a.item_number,
a.item_rate,
a.item_code,
a.effective_dt,
r_prev.effective_dt,
r_prev.item_rate,
r.item_code
from A a LEFT OUTER join
(SELECT item_number, item_rate, item_code,effective_dt
FROM A
) a_prev
ON a.item_number = a_prev.item_number
AND a.rating_eff_dt < a_prev.rating_eff_dt
order BY a.item_number, r.item_rate, r.item_code, a.effective_dt desc, a_prev.rating_eff_dt
You can use
Select Number(*),<column list>
from table
Thank You.

Need help in creating CriteriaQuery

First of all, I would like to know if it is possible to do?
Below is my query and I am trying to build using criteria.
SELECT CONCAT('record-', rl.record_id) AS tempId,
'sloka' AS type,
rl.record_id AS recordId,
rl.title AS title,
rl.locale as locale,
rl.intro AS intro,
rl.title AS localetitle,
NULL AS audioUrl,
lp.name AS byName,
lp.person_id AS byId,
lp.name AS onName,
lp.person_id AS onId
FROM record_locale rl
LEFT JOIN record r ON rl.record_id = r.record_id
LEFT JOIN locale_person lp ON r.written_on = lp.person_id
WHERE rl.title LIKE :title
AND rl.locale = :locale
AND lp.locale = :locale
UNION
SELECT CONCAT('lyric-', s.song_id) AS tempId,
'bhajan' AS type,
s.song_id AS recordId,
s.title,
l.locale as locale,
NULL AS intro,
l.title AS localetitle,
s.audio_url AS audioUrl,
lpb.name AS byName,
lpb.person_id AS byId,
lpo.name AS onName,
lpo.person_id AS onId
FROM song s
LEFT JOIN locale_person lpb
ON (s.written_by = lpb.person_id AND lpb.locale = :locale)
LEFT JOIN locale_person lpo
ON (s.written_on = lpo.person_id AND lpo.locale = lpb.locale)
INNER JOIN lyric l
ON (l.locale = lpb.locale AND l.song_id = s.song_id)
WHERE s.title LIKE :title AND s.approved_by IS NOT NULL
ORDER BY localeTitle ASC
// END
Based on few conditions, I might need to have union of both queries or just individual query without union.
Converting the SQL to JPQL is usually a good first step, as we can't quite tell what these tables map to, or what you are expecting to get back. If it is possible to do in JPQL, it should be possible with a criteria query. Except in this case: JPA/JPQL does not have the union operator so it won't work in straight JPA, but some providers such as EclipseLink have support. See:
UNION to JPA Query
and
http://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/j_union.htm

How to return specific properties from a JPA repository?

I'm getting a ClassCastException when retrieving an entity into a resource. It occurs only when the JPA repository statement explicitly specifies the properties to be returned.
For example, this works just fine and there is no exception triggered:
#Query("SELECT r FROM Rollout r, RolloutAdmin ra WHERE r.id = ra.rollout.id AND ra.admin = :admin")
And it renders as:
select rollout0_.id as id1_8_, rollout0_.version as version2_8_, rollout0_.bts_nb_all as bts_nb_a3_8_, rollout0_.country_id as country_9_8_, rollout0_.creation_datetime as creation4_8_, rollout0_.description as descript5_8_, rollout0_.end_datetime as end_date6_8_, rollout0_.name as name7_8_, rollout0_.operator_id as operato10_8_, rollout0_.start_datetime as start_da8_8_ from rollout rollout0_ cross join rollout_admin rolloutadm1_ where rollout0_.id=rolloutadm1_.rollout_id and rolloutadm1_.admin_id=1 order by rollout0_.name asc limit 10;
But this triggers the exception:
#Query("SELECT DISTINCT r.id, r.country, r.operator, r.name, r.description, r.creationDatetime, r.startDatetime, r.endDatetime FROM Rollout r, RolloutAdmin ra, BTS b WHERE b.rollout.id = r.id AND r.id = ra.rollout.id AND ra.admin = :admin GROUP BY r.id")
And it renders as:
select distinct rollout0_.id as col_0_0_, rollout0_.country_id as col_1_0_, rollout0_.operator_id as col_2_0_, rollout0_.name as col_3_0_, rollout0_.description as col_4_0_, rollout0_.creation_datetime as col_5_0_, rollout0_.start_datetime as col_6_0_, rollout0_.end_datetime as col_7_0_, country3_.id as id1_4_0_, operator4_.id as id1_6_1_, country3_.version as version2_4_0_, country3_.code as code3_4_0_, country3_.list_order as list_ord4_4_0_, country3_.name as name5_4_0_, operator4_.version as version2_6_1_, operator4_.country_id as country_9_6_1_, operator4_.description as descript3_6_1_, operator4_.image as image4_6_1_, operator4_.messenger as messenge5_6_1_, operator4_.name as name6_6_1_, operator4_.operator_id as operator7_6_1_, operator4_.url as url8_6_1_ from rollout rollout0_ inner join country country3_ on rollout0_.country_id=country3_.id inner join operator operator4_ on rollout0_.operator_id=operator4_.id cross join rollout_admin rolloutadm1_ cross join bts bts2_ where bts2_.rollout_id=rollout0_.id and rollout0_.id=rolloutadm1_.rollout_id and rolloutadm1_.admin_id=1 group by rollout0_.id order by rollout0_.name asc limit 10;
How come such a difference ? Any way to specify the properties to be returned without fetching the whole dependent parent properties ?
EDIT: I now understand, thanks to Nizet, that I need to return an object of the same type as my repository method.
It's quite simple:
SELECT r FROM Rollout r
means: I want this query to return r, of type Rollout. The query returns a List<Rollout>.
Whereas
SELECT DISTINCT r.id, r.country, r.operator, r.name, r.description, r.creationDatetime, r.startDatetime, r.endDatetime FROM Rollout r
means: I want this query to return many different things: an ID, a country, an operator, etc. Since the query returns many different things, of different types, and potentially from several different entities (not the case in this specific example, but you could also return properties from ra), the query returns a List<Object[]>, where the first element of the array of objects is ID, the second is country, the third is operator, etc.
Not that even your first query is more complex than it should. The association between the two entities already says how the two entities are joined. So all you need is
SELECT r FROM RolloutAdmin ra join ra.rollout r WHERE ra.admin = :admin