I have been struggling with this query for about a week now so any help is appreciated:
SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name, b.id FROM LengthMeasurements l
JOIN l.healthCheck h
JOIN h.bird b
LEFT JOIN (SELECT MAX(w.healthCheck.catchDateTime), AVG(w.weight), w.healthCheck.bird.id as bid FROM WeightMeasurements w WHERE
w.healthCheck.bird.id=1) AS x
ON x.bid = b.id
WHERE b.id=1
GROUP BY b.id, h.id ORDER BY l.healthCheck.catchDateTime DESC LIMIT 1
The query throws an error which complains about Semantics, but not more specific than that:
[2023-08-13 22:29:11] org.hibernate.query.SemanticException: A query exception occurred [SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name, b.id FROM LengthMeasurements l
[2023-08-13 22:29:11] JOIN l.healthCheck h
[2023-08-13 22:29:11] JOIN h.bird b
[2023-08-13 22:29:11] LEFT JOIN (]
[2023-08-13 22:29:11] A query exception occurred [SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name, b.id FROM LengthMeasurements l
[2023-08-13 22:29:11] JOIN l.healthCheck h
In order to debug the query I tried to beak it down:
This works (I removed the inner select:
SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name, b.id FROM LengthMeasurements l
JOIN l.healthCheck h
JOIN h.bird b
WHERE b.id=1
GROUP BY b.id, h.id ORDER BY l.healthCheck.catchDateTime DESC LIMIT 1
And the INNER JOIN
works also on its own:
SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name, b.id FROM LengthMeasurements l
JOIN l.healthCheck h
JOIN h.bird b
WHERE b.id=1
GROUP BY b.id, h.id ORDER BY l.healthCheck.catchDateTime DESC LIMIT 1
So what could be the issue?
Ideally I want my query to return:
| catchDateTime | AVG beakLength | AVG tarsusLength | AVG tarsusWidth | b.name | b.id | AVG weight |
MODEL SETUP
@Entity
@Data
@Table(name="bird")
public class Bird {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String name;
@Enumerated(EnumType.STRING)
private Status status;
@Enumerated(EnumType.STRING)
private Sex sex;
@OneToOne(optional = true)
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "current_transmitter_id", nullable = true)
private Transmitter currentTransmitter;
@OneToOne(optional = true)
@JoinColumn(name = "current_pit_id")
private Pit currentPit;
@JsonBackReference
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "bird")
private List<HealthCheck> listHealthCheck = new ArrayList<>();
Health Check
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Data
@JsonIgnoreProperties({"hibernateLazyInitalizer", "handler"})
@Table(name="HEALTH_CHECK")
public class HealthCheck {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
@JsonManagedReference
@ManyToOne(fetch = FetchType.EAGER, optional = false)
private Bird bird;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="healthCheck")
private List<Task> tasks;
private LocalDateTime catchDateTime;
// constructors and getters & setters
Abstract Class Task
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Data
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name="TASK")
public abstract class Task {
@Id
private Long taskId;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private HealthCheck healthCheck;
// constructors and getters & setters
}
And task can have collections of either LengthMeasurements or WeightMeasurements:
WeightMeasurements
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WeightMeasurements extends Task {
private Double weight;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private HealthCheck healthCheck;
// constructors and getters & setters
}
And finally
LengthMeasurements
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Data
public class LengthMeasurements extends Task {
private Double beakLength;
private Double tarsusLength;
private Double tarsusWidth;
private Double tarsusDepth;
// constructors and getters & setters
Do the relationships between HeatlhCheck and Tasks need to be bi-directional?