Query for distinct instance of model + one other field - mysql

I have a model called Evaluation. When an evaluation is created, an eval_number is created with it. There are many evaluations with the same eval_number.
Here's an example:
- !ruby/object:Evaluation
attributes:
id: 2023
score: 3
created_at: 2013-09-08 13:10:53.000000000 Z
updated_at: 2013-09-08 13:10:53.000000000 Z
student_id: 26
goal_id: 50
eval_number: 33
- !ruby/object:Evaluation
attributes:
id: 2099
score: 4
created_at: 2013-09-08 13:19:12.000000000 Z
updated_at: 2013-09-08 13:19:12.000000000 Z
student_id: 26
goal_id: 36
eval_number: 34
- !ruby/object:Evaluation
attributes:
id: 2100
score: 3
created_at: 2013-09-08 13:19:12.000000000 Z
updated_at: 2013-09-08 13:19:12.000000000 Z
student_id: 26
goal_id: 37
eval_number: 34
- !ruby/object:Evaluation
attributes:
id: 2101
score: 4
created_at: 2013-09-08 13:19:12.000000000 Z
updated_at: 2013-09-08 13:19:12.000000000 Z
student_id: 26
goal_id: 38
eval_number: 34
In a view, I want to show the date that a given evaluation was created in a table header. It should look like this:
date_1 | date_2 | date_3 | date_4 | etc..
To do this, I need to get distinct evaluation_numbers + the created_at dates that go with them. I thought that this would help, but it's returning more than one record per eval_number with this code:
def eval_date(i)
evals = self.goals.first.evaluations
eval = evals.select("distinct(eval_number), created_at").all[i]
eval.created_at.to_date
end
It seems like distinct eval_numbers are being selected, but also distinct created_at columns (which of course are all different). This makes the .all[i] basically useless as it's finding the [0], [1], [2], etc element correctly - but there are far more than whatever the given number of i is in the returned array.
I want to find a distinct eval_number and load only the created_date that goes with it. I think I could load the whole record with all attributes, but I don't need them, so I'd rather not.

Try this:
def eval_date(i)
evals = self.goals.first.evaluations
eval = evals.order("eval_number").group(:eval_number).all[i]
eval.created_at.to_date
end
PS: if you are calling eval_date repeatedly then cache the evaluations like so
def eval_date(i)
#evals ||= self.goals.first.evaluations.order("eval_number").group("eval_number").all
eval = #evals[i]
eval.created_at.to_date
end

got it working like this, but i'm open to better suggestions:
#student.rb
def eval_date(i)
eval = self.goals.first.evals_by_number.values[i].first
eval.created_at.strftime("%d %b, %Y")
end
#goal.rb
def evals_by_number
self.evaluations.order("eval_number").group_by(&:eval_number)
end

Related

In groovy, how can i iterate over a csv file and call a function for every "group" that as a different value on some of the columns?

In Groovy and running on a jenkins pipeline, I am using the readFile function from jenkins to read the csv file.
Example csv:
name
val1
val2
John
2
122
John
2
012
Bertha
2
0021
John
3
20
Philip
3
12022
Bertha
3
162021
John
3
2022
What I am trying to achieve is call another function for each different value in column "name".
The Groovy script flow would be something like:
call functionX (name, rest of values) with:
name
val1
val2
John
2
122
John
2
012
John
3
20
John
3
2022
then call functionX (name, rest of values) with:
name
val1
val2
Philip
3
12022
then call functionX (name, rest of values) with:
name
val1
val2
Bertha
2
0021
Bertha
3
162021
Note:
The order (John, Philip, Bertha) is not important!
I think i can achieve this with closures but I'm not quite sure since I'm pretty new to the topic
Is this something like what you are looking for?
def functionX(name,val1,val2) {
if (name == 'name') return
println ( "Name: $name, V1: $val1, V2: $val2" )
}
new File( 'names.csv' ).readLines().sort{ it }.each {
println it
functionX( *( it.split( ',' ) ) )
}
Output:
Bertha,2,21
Name: Bertha, V1: 2, V2: 21
Bertha,3,162021
Name: Bertha, V1: 3, V2: 162021
John,2,12
Name: John, V1: 2, V2: 12
John,2,122
Name: John, V1: 2, V2: 122
John,3,20
Name: John, V1: 3, V2: 20
John,3,2022
Name: John, V1: 3, V2: 2022
Philip,3,12022
Name: Philip, V1: 3, V2: 12022
name,val1,val2

IN statement with mysql JSON column not working?

I am trying to query MySQL table on json column data not working as expected
JSON_EXTRACT(data, \"$.STUDENT_NAME\") IN ('JASMINE','SAM')
where as this JSON_EXTRACT(data, \"$.STUDENT_NAME\") IN ('JASMINE') works with only one element but not with multiple elements in the array, any ideas?
complete query
SELECT `data_uploads`.* FROM `data_uploads` WHERE `data_uploads`.`product_id` = 96 AND (dlname = 'STUDENT' AND JSON_EXTRACT(data, \"$.STUDENT_NAME\") IN ('JASMINE', 'SAM'))
expected results
product_id: 96, dlname: "STUDENT", data: {"CLASS"=>"GRADE-I", "GRAD_IMAGE"=>"jasmine_grad.jpg", "SECTION"=>"A", "STUDENT_IMAGE"=>"jasmine.jpg", "STUDENT_NAME"=>"JASMINE"}, created_at: "2021-06-18 10:16:56", updated_at: "2021-06-18 10:16:56"
product_id: 96, dlname: "STUDENT", data: {"CLASS"=>"GRADE-I", "GRAD_IMAGE"=>"sam_grad.jpg", "SECTION"=>"A", "STUDENT_IMAGE"=>"sam.jpg", "STUDENT_NAME"=>"SAM"}, created_at: "2021-06-18 10:16:56", updated_at: "2021-06-18 10:16:56"
but the above query returns an empty array
Rails active record query:
DataUpload.where(product_id: 96).where("dlname = 'STUDENT' AND JSON_EXTRACT(data, '$.STUDENT_NAME') IN ('JASMINE','SAM')")
Use JSON_UNQUOTE() to remove the quotes around the value before testing it.
SELECT *
FROM data_uploads
WHERE JSON_UNQUOTE(JSON_EXTRACT(data, "$.STUDENT_NAME")) IN ('JASMINE','SAM');
You can also use the ->> shorthand to extract and unquote at once.
SELECT *
FROM data_uploads
WHERE data->>"$.STUDENT_NAME" IN ('JASMINE','SAM');

Selecting all the records from table to which given number belongs to

Suppose I have following three records in my model :
#<Rda:0xf6e8a0c
id: 1,
age_group: "18-100",
weight: "60",
nutrient: "energy(kcal/day)",
value: "2730",
created_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00,
updated_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00>
#<Rda:0xf6e8a0c
id: 2,
age_group: "10-15",
weight: "60",
nutrient: "energy(kcal/day)",
value: "2730",
created_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00,
updated_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00>
#<Rda:0xf6e8a0c
id: 3,
age_group: "20-100",
weight: "60",
nutrient: "energy(kcal/day)",
value: "2730",
created_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00,
updated_at: Sat, 15 Oct 2016 08:21:43 UTC +00:00>
Now, I want to get all those records in which my given value falls in a 'age_group' columns ranges. For example: suppose my age is 25 then I should get records with ids 1 & 3 from the above records because '25' falls in between '18-100' and '20-100'
You might do
def self.foo(age)
all.select { |rda| Range.new(*rda.age_group.split('-').map(&:to_i)).cover? age }
end

Query has_many relationship, contains this and also this

# engine.rb
has_many :pistons
#piston.rb
belongs_to :engine
Piston has a column, piston_count and, of course, engine_id
My database has the following 7 records
Engine.all
#=> [#<Engine id: 1>, #<Engine id: 2>, #<Engine id: 3>]
Piston.all
#=> [#<Piston id: 1, engine_id: 1, piston_count: 1>, #<Piston id: 2, engine_id: 1, piston_count: 2>, #<Piston id: 2, engine_id: 2, piston_count: 1>, #<Piston id: 2, engine_id: 3, piston_count: 2>]
I want to write a query that says, return the Engine containing Pistons with a piston_count of 1 and also contains a piston_count of 2
I've tried...
engines = Engine.joins(:pistons).merge(Piston.where(piston_count: 1))
#=> [#, #]
engines.joins(:pistons).merge(Piston.where(piston_count:2))
#=> []
It returns an empty array because active record turns that into one AND clause. However, if I do an OR statement, it will return too many records. Any thoughts?
Figured it out. This takes the intersect of both Active Record Queries.
engine_ids = Engine.joins(:pistons).merge(Piston.where(piston_count: 1)).pluck(:id) & Engine.joins(:pistons).merge(Piston.where(piston_count: 2)).pluck(:id)
Then go back and retrieve all the intersects.
Engine.where(id: engine_ids)

Searching through databases serialized column

In MySQL Rails 3 application, one of my columns are serialized to Hash. My question is simple: how can I get results based on this column?
I tried this approach:
example_hash = {id: 666}
ExampleTable.last.hash == example_hash
:true ###### Here you can see that both hashes are the same
Still, a query like this give me no results and no exceptions:
ExampleTable.where('hash LIKE ?', example_hash)
It just doesn't detect the record I need.
my_hash = {id:666}
search_term = my_hash.serializable_hash
ExampleTable.where(search_term)
I tried this in an existing Rails 4 app. You will have to test if it works in Rails 3. I don't have include ActiveModel::Serialization in my model and it still works.
Here is my console session:
Loading development environment (Rails 4.0.0)
$pry(main)> t = Tool.first
Tool Load (10.9ms) SELECT "tools".* FROM "tools" ORDER BY "tools"."id" ASC LIMIT 1
=> #<Tool id: 2, name: "6", serial: "134989652", purchased: nil, put_in_service: nil, cost: nil, value: nil, in_service: true, retired: nil, created_at: "2013-07-17 06:12:59", updated_at: "2014-02-13 17:19:10", note: "", condition: "5 - Brand New Condition", old_location: "Sta 75", model: "Stihl 066", loaner: false, location_id: 9, category_id: 2, annual_service: false>
$pry(main)> x = t.serializable_hash
=> {"id"=>2,
"name"=>"6",
"serial"=>"134989652",
"purchased"=>nil,
"put_in_service"=>nil,
"cost"=>nil,
"value"=>nil,
"in_service"=>true,
"retired"=>nil,
"created_at"=>Tue, 16 Jul 2013 23:12:59 PDT -07:00,
"updated_at"=>Thu, 13 Feb 2014 09:19:10 PST -08:00,
"note"=>"",
"condition"=>"5 - Brand New Condition",
"old_location"=>"Sta 75",
"model"=>"Stihl 066",
"loaner"=>false,
"location_id"=>9,
"category_id"=>2,
"annual_service"=>false}
$pry(main)> Tool.where(x)
Tool Load (10.3ms) SELECT "tools".* FROM "tools" WHERE "tools"."id" = 2 AND "tools"."name" = '6' AND "tools"."serial" = '134989652' AND "tools"."purchased" IS NULL AND "tools"."put_in_service" IS NULL AND "tools"."cost" IS NULL AND "tools"."value" IS NULL AND "tools"."in_service" = 't' AND "tools"."retired" IS NULL AND "tools"."created_at" = '2013-07-17 06:12:59.638381' AND "tools"."updated_at" = '2014-02-13 17:19:10.674233' AND "tools"."note" = '' AND "tools"."condition" = '5 - Brand New Condition' AND "tools"."old_location" = 'Sta 75' AND "tools"."model" = 'Stihl 066' AND "tools"."loaner" = 'f' AND "tools"."location_id" = 9 AND "tools"."category_id" = 2 AND "tools"."annual_service" = 'f'
=> [#<Tool id: 2, name: "6", serial: "134989652", purchased: nil, put_in_service: nil, cost: nil, value: nil, in_service: true, retired: nil, created_at: "2013-07-17 06:12:59", updated_at: "2014-02-13 17:19:10", note: "", condition: "5 - Brand New Condition", old_location: "Sta 75", model: "Stihl 066", loaner: false, location_id: 9, category_id: 2, annual_service: false>]