Spring data JPA repository order by condition - mysql

I have a Product entity which contains some attributes, I need to get the closest products to a given product depending on some criteria, the criteria are category, finish and production company.
I wrote this query
#Query("Select pr from Product pr ORDER BY (CASE WHEN (pr.category = :p.category) THEN 1 WHEN (pr.finish = :p.finish) THEN 2 WHEN (pr.productionCompany = :p.productionCompany) THEN 3 ELSE 4 ) LIMIT 5")
List<Product> findRecommendedProducts(#Param("p")Product p);
But this keeps giving me the following exception
antlr.MismatchedTokenException: expecting "end", found ')'
Any help is appreciated.

I think you need to add ELSE 4 END to your query. I assume this is running on Oracle?

Related

Get second highest date from related table

I am trying to fetch the second highest date from a relation-table in with Eloquent Laravel 6.
MoodTable
id animal_id date mood
1 1 2019-12-14 happy
2 1 2019-12-11 drunk
3 1 2019-12-13 sad
AnimalTable
id name
1 Dog
So for example, I want to be able to query: "Today Dog is happy. Prevously to that he was Drunk.
To fetch the highest I use:
return $this->hasMany('App\AnimalMood', 'animal_id')->select(DB::raw('
mood,
animal_id,
MAX(date) as max_date,
'))
->groupBy('stock_id');
However, when it comes to seconed highest date... I'm out...
I have looked at How to return second newest record in SQL?
for some answers,but not been able to put that in a relationship senario nor translate it to Eloquent.
Ideally, I would like to run Animal::with('moodPrevious')->get() and Animal::find(1)->moodPrevious from my controller...
I would change the relationship and grab all of the related models to your Animal model when you query for it.
return $this->hasMany('App\AnimalMood', 'animal_id');
Below returns the animals with the moods pre-sorted.
$animals = Animal::with(['mood' => function($q){
$q->orderByDesc('date');
}])->get();
Laravel offers a lot of collection methods that work well with related models. I would use the callback you can provide to first() in order to get the mood you want on the model. You probably already have the specific model you want, either by foreaching over the above collection or something similar. The relation will be a collection instance so we use the collection method to get the mood desired.
$previousMood = $animal->mood->first(function($value, $key){
return $key == 1 // You can use whatever here, this will return the second item on the relation, or the previous mood.
});
See https://laravel.com/docs/5.8/collections#method-first for a reference.
I think this would work
return $this->hasMany('App\AnimalMood', 'animal_id')
->select(
DB::raw('
mood,
animal_id,
MAX(date) as max_date,
')
)
->where(
DB::raw("
date = (
SELECT
MAX(date)
FROM animal_moods
WHERE date < (
SELECT
MAX(date)
FROM
animal_moods
)
)
")
)
->groupBy('stock_id');

MYSQL - How to group by with condition

Here's an example of the tables and outputs I want
I want to group by by no reg with condition, status = 0 but if in table activity there is no status = 0 then that will be selected is with biggest id
You may only need this query.
Select no_reg, location from activities where status = 0
Check the result and run another query.
if (result == null){ //for example run the query below
Select no_reg, location from activities desc limit 1
}
From the image what you want is activities of the equipment i believe
for example if you want to check the equipment A1 Malaysia should be list or one with biggest status will be listed i believe
if thats what you want here it is
SELECT no_reg,MAX(status) FROM activities a,equipment e on e.no_reg=a.no_reg where e.no_reg='A1' group by a.no_reg
i believe this is the solution you are expecting

SQL Script for Counting Records based on specific criteria and returning the Counts

I'm Trying to count records with specific criteria in my Database to ultimately produce some statistical reports.
My Tables and Fields are:
1- Import Table:bed_ID, unit_ID, mrn, acccount_num, sex, service_ID
2- Beds: bed_ID, unit_ID, bed_type_ID
3- Bed_Type: bed_type_ID, bed_type_description
4- Unit: unit_ID, unit_common_name, program_ID, total_beds...other fields that don't apply.
5- Service: service_ID, service_common_name, program_ID
6- Program: program_ID, program_common_name
I want to create a query that will give me a count of each Bed_Type_Description for each Unit. I also want to get each units total beds and calculate beds available but I'm sure I can figure that out if I get help with this part.
Unit Regular_Bed Escalation_Bed Transfer_Bed Bassinet
-------------------------------------------------------------
Unit1 10 4 2 2
Unit2 12 2 2 0
etc...
etc...
This is what I have, but its only related to one specific Unit:
SELECT
COUNT(dw_test.dbo.Bed_Type.bed_type_description) as 'Total Number of Beds'
FROM
dw_test.dbo.MediTechReport_Bed_Board,
--dw_test.dbo.Unit,
dw_test.dbo.Beds,
dw_test.dbo.Bed_Type
WHERE
dw_test.dbo.MediTechReport_Bed_Board.bed_ID = dw_test.dbo.Beds.bed_ID
--AND
-- dw_test.dbo.MediTechReport_Bed_Board.unit_ID = dw_test.dbo.Unit.unit_ID
AND
dw_test.dbo.Beds.bed_type_ID = dw_test.dbo.Bed_Type.bed_type_ID
AND
dw_test.dbo.MediTechReport_Bed_Board.unit_ID = 'KA2MED'
AND
dw_test.dbo.Bed_Type.bed_type_description = 'Regular';
You'll notice a couple lines related to Unit that are commented out. With these commented out I get a returned value of '5' records which is correct. If i remove the commenting to include these lines it returns a value of '0' which makes no sense to me. If someone can explain this to me that'd be great as well.
My SQL is quite rusty, its been a while. Any assistance is greatly appreciated. Thanks again in advance for all your help.
Maybe something like this?
select t.bed_type_description, COUNT(t.bed_type_description) as 'Total Number Of Beds'
from import As I inner join Beds as b on i.bed_Id = b.bed_Id
inner join Unit as u on i.unit_Id = u.unit_Id
inner join Bed_Type as t on b.bed_type_Id = t.bed_type_Id
where u.unit_Id = 'KA2MED'
group by t.bed_type_description

Can SQL query do this?

I have a table "audit" with a "description" column, a "record_id" column and a "record_date" column. I want to select only those records where the description matches one of two possible strings (say, LIKE "NEW%" OR LIKE "ARCH%") where the record_id in each of those two matches each other. I then need to calculate the difference in days between the record_date of each other.
For instance, my table may contain:
id description record_id record_date
1 New Sub 1000 04/14/13
2 Mod 1000 04/14/13
3 Archived 1000 04/15/13
4 New Sub 1001 04/13/13
I would want to select only rows 1 and 3 and then calculate the number of days between 4/15 and 4/14 to determine how long it took to go from New to Archived for that record (1000). Both a New and an Archived entry must be present for any record for it to be counted (I don't care about ones that haven't been archived). Does this make sense and is it possible to calculate this in a SQL query? I don't know much beyond basic SQL.
I am using MySQL Workbench to do this.
The following is untested, but it should work asuming that any given record_id can only show up once with "New Sub" and "Archived"
select n.id as new_id
,a.id as archive_id
,record_id
,n.record_date as new_date
,a.record_date as archive_date
,DateDiff(a.record_date, n.record_date) as days_between
from audit n
join audit a using(record_id)
where n.description = 'New Sub'
and a.description = 'Archieved';
I changed from OR to AND, because I thought you wanted only the nr of days between records that was actually archived.
My test was in SQL Server so the syntax might need to be tweaked slightly for your (especially the DATEDIFF function) but you can select from the same table twice, one side grabbing the 'new' and one grabbing the 'archived' then linking them by record_id...
SELECT
newsub.id,
newsub.description,
newsub.record_date,
arc.id,
arc.description,
arc.record_date,
DATEDIFF(day, newsub.record_date, arc.record_date) AS DaysBetween
FROM
foo1 arc
, foo1 newsub
WHERE
(newsub.description LIKE 'NEW%')
AND
(arc.description LIKE 'ARC%')
AND
(newsub.record_id = arc.record_id)

Fetch timestamped counts from multiple tables

I have a table of nodes:
nid type created status
2 blog 134292319 1
3 forum 134292536 1
4 blog 135921392 0
To graph the number of published (status=1) nodes over time, I execute this query:
SELECT created, type
FROM node WHERE status = 1
ORDER BY created
I then go through this data set in PHP, splitting it into timestamped groups with a node count associated with each group. The results are cached, so slow execution isn't a problem.
I also have a table of comments:
nid timestamp status
2 134292363 1
3 134293234 1
I want to incorporate forum comment counts into the graph of node counts.
To get the comment counts, I would run this query:
SELECT timestamp
FROM comments
INNER JOIN node ON comments.nid = node.nid
WHERE
node.type = 'forum'
AND comments.status = 1
ORDER BY timestamp
I need to somehow combine these two queries, to end up with (for the examples given):
created type
134292319 blog
134292536 forum
134293234 forum_comment
Any ideas?
Thanks.
This will get you your example output but I am not sure it's exactly what you are looking for based on your description of the question.
SELECT created, type FROM
(
SELECT created, type
FROM node WHERE status = 1
UNION ALL
SELECT timestamp as created, 'forum_comment' as type
FROM comments
INNER JOIN node ON comments.nid = node.nid
WHERE node.type = 'forum'
AND comments.status = 1
) AS U
ORDER BY U.created