Use GROUP_CONCAT query in Rails - mysql

I need the ids of a table but #pluck is not fast enough because there are too many records.
The thing is that I would like to get them in a string directly from mysql instead of get any Array or ActiveRecord::Relation
[1, 2, 3] => "1,2,3"
There is no group_concat in Rails, so I just asked via sql. Example:
sql = User.select("GROUP_CONCAT(users.id)").to_sql
ActiveRecord::Base.connection.exec_query(sql)
The thing is that I don't know why but it does not return all the ids of the table, but just some of them.
Any idea why is not returning all of them or how can I achieve it in a different way?

Apparently the result is truncated to the maximum length that is given by the group_concat_max_len.
Maybe you could increase that value. Follow this answer to get more information:
https://stackoverflow.com/a/5545904/8195530

You could just call it like this
sql = "select GROUP_CONCAT(id) from users"
data = ActiveRecord::Base.connection.exec_query(sql)
# #<ActiveRecord::Result:0x0000560661a2b7d8 #columns=["ids"], #rows=[["41,40,38,42,39,43,45,44"]], #hash_rows=nil, #column_types={}>
then you can get the data as ids with
ids = data['ids'].split(',').map(&:to_i)
# [41, 40, 38, 42, 39, 43, 45, 44]

Related

Use object keys given by JSON_SEARCH to find a different key in the same object in mysql/mariadb

I have some records of payments in the database and I keep the items belonging to the payment as a JSON(LONGTEXT) column in mariadb. For example the items columns would be like below.
items
[{"id":"a4","quantity":1,"title":"A4 Sheets","unitprice":7000,"total":7000},{"id":"reports","quantity":1,"title":"Reports","unitprice":750,"total":750},{"id":"other","quantity":2,"title":"Cap","unitprice":250,"total":500}]
[{"id":"exam3_5","quantity":1,"title":"Exam Fees : Grade 03 - 05","unitprice":750,"total":750},{"id":"a4","quantity":1,"title":"A4 Sheets","unitprice":7000,"total":7000},{"id":"reports","quantity":1,"title":"Reports","unitprice":750,"total":750}]
[{"id":"other","quantity":10,"title":"Test1","unitprice":1,"total":10},{"id":"other","quantity":10,"title":"Test2","unitprice":2,"total":20}]
what I want to do is find objects that have the id of "other" and get the total of each object.
I can get objects with other by JSON_SEARCH(items, 'all', 'other')
and it will give results like below, just an example. Not according to the first table.
JSON_SEARCH(items, 'all', 'other')
"$[2].id"
["$[0].id", "$[1].id"]
So i know which indexes of the array have i need to look at. Now i need to get the total of every object which has id as "other".
I can do a JSON_EXTRACT(items, '$[*].total') which gives me
JSON_SEARCH(items, 'all', 'other')
JSON_EXTRACT(items, '$[*].total')
"$[2].id"
[7000, 750, 500]
["$[0].id", "$[1].id"]
[10, 20]
I need a third column something like this
JSON_SEARCH(items, 'all', 'other')
JSON_EXTRACT(items, '$[*].total')
Required Column
"$[2].id"
[7000, 750, 500]
500
["$[0].id", "$[1].id"]
[10, 20]
30
Finally I want a cumulative total of the "Required Column" which I guess I can do by SUM(Required Column).
Any advice on achieving the "Required Column"?
I'm using nodejs as the backend. I could do the processing there but I want to know if it can be done with mysql itself.
Thanks

SQL Alchemy: add a func(count) result field in each element of my list

I'm struggling to add a number using a func(count) within a car object on sql Alchemy. An example will make it clearer:
query = session.query(Car, func.count(Car.id).label('cars_total'))
query = Car.query.join(Color, Car.color.id= color.id)
.group_by(color_id)
The result is something like:
[(<Car>, 8), (<Car>, 3), (<Car>, 7)... ] and i'm looking for:
`
[<Car>, <Car>, <Car>] with Car[0].__dict__ including the car_total
How can I do that?

mysql query works in phpmyadmin but not in node.js

I have a query like this...
SELECT *
FROM `000027`,`000028`
WHERE `000027`.id=(SELECT max(`000027`.id) FROM `000027`)
AND `000028`.id=(SELECT max(`000028`.id) FROM `000028`)
which returns something like this in phpmyadmin...
id time value id time value
However, in react.js it is only returning one of these like this...
id time value
2 questions, Why is it doing this? and, how can I get it to return both instead of one?
my node.js code...
const sqlSelect = "SELECT * FROM `000027`,`000028` WHERE `000027`.id=(SELECT max(`000027`.id) FROM `000027`) AND `000028`.id=(SELECT max(`000028`.id) FROM `000028`)"
dbPlant.query(sqlSelect, (err, result) => {
console.log(result)
res.send(result)
res.end()
})
and it sends this back with only one rowdatapacket when it should be two, or two of each of those values...
[
RowDataPacket {
id: 652,
time: 2021-01-24T17:28:01.000Z,
value: '262'
}
]
Your two tables have some column names in common. This is okay to have repeated column names in a result set in the mysql client, but some programming interfaces map a rows of a result set into a hash array, where the column names are the keys. So if you have duplicate column names, one naturally overwrites the other.
The remedy is to define column aliases for one or the other of each duplicate, so they are mapped into distinct keys in the result set.
You must do this one column at a time. Sorry, you can't use SELECT * anymore (you shouldn't use SELECT * anyway). There is no "automatic alias all columns" option.
SELECT
`000027`.id AS id27,
`000027`.time AS time27,
`000027`.value AS value27,
`000028`.id AS id28,
`000028`.time AS time28,
`000028`.value AS value28
FROM `000027`,`000028`
WHERE `000027`.id=(SELECT max(`000027`.id) FROM `000027`)
AND `000028`.id=(SELECT max(`000028`.id) FROM `000028`)

Mysql for NodeJS not expanding array in queries

I'm using NodeJS and the mysql package from npm. I'm having trouble selecting specific rows from the database by ID. I'm using a simple WHERE id IN (...) query, and passing in the ids as an array of numbers.
According to the documentation,
Arrays are turned into list, e.g. ['a', 'b'] turns into 'a', 'b'
So I've written this code to debug the SQL it generates:
console.log(ids);
console.log(this.connection.format(
"SELECT `invitations`.* FROM `invitations` WHERE `invitations`.`id` IN (?)",
ids
));
I expect to see a list of ids first, then the SQL statement where those ids are in the IN section of the query.
However, only the first id is present in the query:
console.log tests/fakers/InvitationFaker.ts:70
[ 207, 208 ]
console.log tests/fakers/InvitationFaker.ts:71
SELECT `invitations`.* FROM `invitations` WHERE `invitations`.`id` IN (207)
Why doesn't the query look like this:
... WHERE `invitations`.`id` IN (207, 208)
?
try to convert the ids to string with "," between the ids
this.connection.format(
"SELECT `invitations`.* FROM `invitations` WHERE `invitations`.`id` IN (?)",
ids.join(",")
));
I'm an idiot :) I forgot that the second argument can be either a single value or an array, but when it's an array, the first value fills the first ? and so on. To expand an array, I need to do this:
" ... WHERE `id` IN ?", [ids]
(note the double array, since ids is already an array). For example:
" ... WHERE `id` IN ?", [[1, 2, 3, 4]]

SQLite3::SQLException: no such column: parameters.user:

I am saving a list of followed users to the db and then trying to get the records where the current user is a part of that list but keep getting this exception.
SQLite3::SQLException: no such column: parameters.user: SELECT "activities".* FROM "activities" WHERE "parameters"."user" = 3
This is a record in the db
=> #<PublicActivity::Activity id: 107, trackable_id: 16, trackable_type: "Shout", owner_id: 1, owner_type: "User", key: "shout.shout", parameters: {:user=>[3]}, recipient_id: nil, recipient_type: nil, created_at: "2015-10-20 21:44:41", updated_at: "2015-10-20 21:44:41", read: false>
These are the queries I've tried that give me this. current_user.id = 3
PublicActivity::Activity.where({'parameters.user' => current_user.id})
PublicActivity::Activity.where(parameters: {user: current_user.id})
So. How do I get the records where the current user is a part of that list of users? Also, would the I be able to use the same query in Mysql?
Might seem like a silly question, but is the parameters column defined as a serialized column in the model? With adapters like MySQL and (I believe) SQLite you can't query serialized fields. So If it's something that you'd like to query, you need to save it separately from the serialized field.
That being said, with PostgreSQL and their rails adapter, you can query serialized fields.
You should check out this SO question and this anser