Select one row with same id and match value in another column from another table - sql

I'm currently working on a Spring Boot Webapp where I want to retreive tasks with JPA.
A Task can have multiple requirements and my customer creates requirement_answers which are connected to his wedding. I now want to select all tasks where all the requirement.answer_value are answered with 'true'.
My relevant Database Schema is:
My current query is this:
I now want to check that the task with the same uuid has all requirement_answer with true?
How can I achieve this?
Greetings
EDIT:
My Solution, filtered in Code instead of jpql as I could not get it working
#Query("""
select t, ra
from
Task t,
RequirementAnswer ra,
Requirement r,
Wedding w
where
ra.requirement = r and
w.id = :weddingId and
t member of r.tasks"
""")
fun findByWedding(weddingId: Long): List<Tuple>?
}
Here is the filtering:
fun getTasksByWedding(wedding: Wedding?): List<Task> {
val tasks: MutableMap<Task,String> = mutableMapOf()
wedding?.id?.let { taskRepository.findByWedding(it) } ?.map {
val task = it.get(0) as Task
val requirementAnswer = it.get(1) as RequirementAnswer
tasks[task]?.let { taskAnswer ->
if(taskAnswer != requirementAnswer.answerValue){
tasks.remove(task)
}
}?: let {
if(requirementAnswer.answerValue == "true"){
tasks[task] = requirementAnswer.answerValue
}
}
} ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Wedding doesn't exist")
return tasks.map { it.key }
}

With SQL you can do use subselects to compare the counts:
select t.*
from task t
join task_requirement tr on t.uuid = tr.task_id
join requirement r on tr.requirement_id = r.id
join requirement_answer ra1 on r.id = ra1.requirement_id
join wedding_requirement_answer wra1 on ra1.id = wra1.requirement_answer_id
where wra1.wedding_id = 1
and ( (select ra2.requirement_id
from requirement_answer ra2
join wedding_requirement_answer wra2 on ra2.id = wra2.requirement_answer_id
where wra2.wedding_id = wra1.wedding_id
and ra2.requirement_id = ra1.requirement_id))
=
(select ra3.requirement_id
from requirement_answer ra3
join wedding_requirement_answer wra3 on ra3.id = wra3.requirement_answer_id
where wra3.wedding_id = wra1.wedding_id
and ra3.requirement_id = ra1.requirement_id
and ra3.answer_value = 'true');

Related

How to combine Flux and Mono

Assume we have the following function
fun getAnnualData(tenant: String): Flux<DashboardResponse> {
val year = LocalDate.now().year
val annualExpenses = expenseFinder.sumAllByYearAndTenant(year = year, tenant = tenant)
val warehouseExpenses = expenseFinder.sumWarehouseByYearAndTenant(year = year, tenant = tenant)
val annualRevenues = revenueFinder.sumAllByYearAndTenant(year = year, tenant = tenant)
return annualExpenses.zipWith(annualRevenues)
.filter { it.t1._id?.year == year }
.filter { it.t2._id?.year == year }
.map {
DashboardResponse(
period = Period.ANNUAL,
expenses = it.t1,
revenue = it.t2
)
}
}
and I want to add the warehouseExpenses to the returning value. How would I do that?
Where
annualExpenses = Flux
warehouseExpenses = Mono
annualRevenue = Flux
You can simply use a flatMap to combine Mono:
Flux.just(...).zipWith(Flux.just(...))
.filter(...)
.flatMap(tuple -> Mono.just(true).map(m -> new DashboardResponse(tuple.getT1(), tuple.getT2(), m)));

Convert SQL Query to query in C#

I've currently got the SQL code below:
WITH region_list
AS (SELECT r.StateProvinceRegion,
r.CafeId,
s.Longitude,
s.Latitude,
ROW_NUMBER() OVER(PARTITION BY r.StateProvinceRegion
ORDER BY s.Longitude DESC) AS row_no
FROM CafeAddress r
inner join Restaurant s on s.CafeId = r.CafeId
)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ID,
StateProvinceRegion,
Longitude,
Latitude
FROM region_list
WHERE row_no = 1;
How would I go about adding this query? In my method below I've implemented something similar but I don't understand how to add the WITH clause in.
public VersionResponse GetCafeRegion()
{
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
select new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude };
return new VersionResponse()
{
Data = regionList
};
}
Try the below code once.
public VersionResponse GetCafeRegion()
{
var CafeAddress = new List<CafeAddress>();
var Cafe = new List<Cafe>();
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
group new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude } by cafeAddress.StateProvinceRegion into g
select g;
List<object> finalResult = new List<object>();
int index = 1;
foreach(var gg in regionList)
{
var groupRecord = gg.OrderByDescending(x => x.Longitude).FirstOrDefault();
finalResult.Add(new
{
ID = index++,
groupRecord.StateProvinceRegion,
groupRecord.CafeId,
groupRecord.Latitude,
groupRecord.Longitude
});
}
return new VersionResponse()
{
Data = finalResult
};
}

How to speed up querying same table many times with different conditions?

EF6, asp mvc core and SQL Server are used on the background.
I have to do many queries to the same table with different conditions, f.e.
SELECT COUNT(*) FROM Table1 WHERE a = true
SELECT COUNT(*) FROM Table1 WHERE b = true
SELECT COUNT(*) FROM Table1 WHERE a = true || b = true
SELECT a FROM Table1 WHERE b = true
So 4 queries to Table1 with different conditions. I think that as result I have to read the entire Table1 four times. In pseudo code it might be looking like this.
var res1 = new list();
foreach(var rec in Table1)
{
// read Table1 first time
if(rec.a == true)
{
res1.push(rec);
}
}
var res2 = new list();
foreach(var rec in Table1)
{
// read Table1 second time
if(rec.b == true)
{
res2.push(rec);
}
}
var res3 = new list();
foreach(var rec in Table1)
{
// read Table1 third time
if(rec.a == true || rec.b == true)
{
res3.push(rec);
}
}
var res4 = new list();
foreach(var rec in Table1)
{
// read Table1 fourth time
if(rec.b == true)
{
res4.push(rec);
}
}
I want to know how to read the Table1 only one time and get four different results, like this:
var res1 = new List();
var res2 = new List();
var res3 = new List();
var res4 = new list();
foreach(rec in Table1)
{
// read Table1 first time
if(a == true)
{
res1.push(rec);
}
if(b == true)
{
res2.push(rec);
}
if(a == true || b == true)
{
res3.push(rec);
}
if(b == true)
{
res4.push(rec);
}
}
Also the challenge, that those queries are dynamic sql, I mean that a = true, b = true, a = true || b = true are stored in database. And queries are running in this way:
string query = "SELECT Count(*) FROM Table1 WHERE" + condition;
var count = ExecuteSql(query);
The sample above is simplified, but in reality all the query is split and stored in database.
PS. Actually I want to speed up the page, which makes 30-40 requests to the server and each request is the query to the same table. I think if I can replace them with one request instead of 40 requests.
You may use conditional aggregation with just a single query:
SELECT
COUNT(CASE WHEN a = true THEN 1 END) AS cnt_a,
COUNT(CASE WHEN b = true THEN 1 END) AS cnt_b,
COUNT(CASE WHEN a = true OR b = true THEN 1 END) AS cnt_a_b
FROM Table1;
This would reduce the number of full table scans from 3 to just 1. Also, it would also potentially reduce the number of round trips to/from the database from 3 to 1.

SQL query to LinqToSql

I have this SQL query that I want to translate into Linq-to-SQL:
Now here's the beginning of the Linq-to-SQL code but I'm stuck on how to group fields and get SUM :
private void GetDatas()
{
DateTime d = DateTime.Now;
using (DataClasses1DataContext dc = new DataClasses1DataContext())
{
var query = from ent in dc.STK_ABC_ENT
join det in dc.STK_ABC_DET on ent.ENT_ID equals det.ENT_ID
join art in dc.FICHES_ARTICLES on ent.ART_CODE equals art.ART_CODE
where !ent.ENT_NUM_PAL.Contains("FDR_")
&& ent.ENT_OUTDATE == null
&& ent.ENT_PICKING == null
&& ent.ENT_DATE_ENT != d
// How to group here ?
// How to get SUM ??
}
}
You can use group x by ColumnName into z to group a column.
When you want to group multiple columns you can use group x by new { x.Column1, x.Column2 } into z.
When you want to group multiple columns in multiple tables you can use group new { x, y } by new { x.Column, y.Column } into z.
With Sum, just call it in select with lamda expression.
Example:
var query = from ent in dc.STK_ABC_ENT
join det in dc.STK_ABC_DET on ent.ENT_ID equals det.ENT_ID
join art in dc.FICHES_ARTICLES on ent.ART_CODE equals art.ART_CODE
where !ent.ENT_NUM_PAL.Contains("FDR_") && ent.ENT_OUTDATE == null
&& ent.ENT_PICKING == null && ent.ENT_DATE_ENT != d
group new { art, ent } by new {
art.ART_CODE,
...,
ent.ENT_DATE_ENT,
...
} into grouped
select new {
ArtCode = grouped.Key.ART_CODE,
SumPdsNet = grouped.Sum(x => x.DET_PNET),
...
}
I hope it can work for you.

Squeryl geo queries with a postgres backend?

How can I perform geo queries using Squeryl with a postgres backend? The sort of queries I want to run are "return all users within x kilometres", etc.
If geo queries aren't supported directly/through a plugin, how can I run raw SQL queries? I saw one gist and it looked complicated.
Update
Specifically I want to run the following query:
SELECT events.id, events.name FROM events
WHERE earth_box( {current_user_lat}, {current_user_lng},
{radius_in_metres}) #> ll_to_earth(events.lat, events.lng);
This is taken from http://johanndutoit.net/searching-in-a-radius-using-postgres/
This object should solve your problem.
object object RawSql {
def q(query: String, args: Any*) =
new RawTupleQuery(query, args)
class RawTupleQuery(query: String, args: Seq[Any]) {
private def prep = {
val s = Session.currentSession
val st = s.connection.prepareStatement(query)
def unwrap(o: Any) = o match {
case None => null
case Some(ob) => ob.asInstanceOf[AnyRef]
case null => null
case a#AnyRef => a
case a#_ => a
}
for(z <- args.zipWithIndex) {
st.setObject(z._2 + 1, unwrap(z._1))
}
st
}
def toSeq[A1]()(implicit f1 : TypedExpressionFactory[A1,_]) = {
val st = prep
val rs = st.executeQuery
try {
val ab = new ArrayBuffer[A1]
val m1 = f1.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A1]]
while(rs.next)
ab.append(m1.convertFromJdbc(m1.extractNativeJdbcValue(rs, 1)))
ab
}
finally {
rs.close()
st.close()
}
}
def toTupleSeq[A1,A2]()(implicit f1 : TypedExpressionFactory[A1,_], f2 : TypedExpressionFactory[A2,_]) = {
val st = prep
val rs = st.executeQuery
try {
val ab = new ArrayBuffer[(A1,A2)]
val m1 = f1.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A1]]
val m2 = f2.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A2]]
while(rs.next)
ab.append(
(m1.convertFromJdbc(m1.extractNativeJdbcValue(rs, 1)),
m2.convertFromJdbc(m2.extractNativeJdbcValue(rs, 2))))
ab
}
finally {
rs.close()
st.close()
}
}
}
}
I got from this gist:
https://gist.github.com/max-l/9250053