sql for a fuzzy search query - mysql

I have an sql query for a mysql database that includes the following
where("UPPER(CONCAT(firstName, ' ', lastName)) LIKE ?", params[:query])
Since sqlite3 doesn't have the concat function, but instead uses pipes ||, I tried to write the above as
where("UPPER(firstName || ' ' || lastName) LIKE ?", params[:query])
but the query isn't returning any results. Am I not using the || correctly?
note, the lowercase where is the Rails query helper.
Update
It turns out that the concat operator wasn't the problem, so I changed the title to this question. I'm trying to do a fuzzy search on a name, namely to return all records that contain the search term in the person's name. For example, if you search "a", "tanja" would be a postive match the server is running this query with my sql
This is the sql that is being run (if an "a" was entered in the search box)
SELECT id, firstname, lastname, title FROM "employees" WHERE (upper(firstName ||' '||lastName) LIKE 'a')
The ajax request (as shown by the console) is this
findByName: a employee.js:20
XHR finished loading: "http://localhost:3000/employees/search/a". jquery.js:8215
[] ##empty array returned
If I run the query in the Rails console, it also returns empty so maybe the problem is with my sql
>> Employee.select("id, firstname, lastname, title").where("upper(firstName ||' '||lastName) LIKE ?", "a")
Employee Load (0.2ms) SELECT id, firstname, lastname, title FROM "employees" WHERE (upper(firstName ||' '||lastName) LIKE 'a')
=> []
However, there are records in the db with names containing the letter "a." This is the database record, for example. Can anyone explain why a query like the above (assuming the person's name contained the searched for letter) wouldn't work on a record like this.
[#<Employee id: 1, firstname: "Steven", lastname: "Wells", managerid: 4, title: "Software Architech", department: "Engineering", officephone: "604-999-8989", cellphone: "345-678-0987", email: "sweels#email.com", city: "Vancouer", picture: "assets/steven_wells.jpg", twitterid: "#fartbreath", blogurl: "http://blahblah.com", created_at: "2013-01-16 01:24:38", updated_at: "2013-01-16 01:24:38">,
Can anyone explain what the problem might be?

I'm not sure, but do you need some wildcards with the "a"? e.g. - "%a%"?

Related

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`)

How do I remove backticks in formatted mysql query?

Okay so I've extracted some values in excel using the npm package 'xlsx' and I want to run a MySql query with the formatted result.
Excel extraction
let wb= xlsx.readFile(filePath); //GET WORKBOOK
let ws= wb.Sheets[wb.SheetNames[0]]; //SELECT THE FIRST SHEET IN THE ARRAY
let data= xlsx.utils.sheet_to_json(ws); //CONVERT DATA TO JSON OBJECT
let s =''; //CREATE VARIABLE TO HOLD FORMATTED STRING
for(let i=0; i<data.length; i++){
s+= "'" + data[i].id +"',"; //FORMAT OBJECT TO STRING
}
let fullString= s.substr(0, s.length-1); //STORE FORMATED STRING IN VARIABLE REMOVING FINAL COMMA (,)
Formated string is like so:
'2019-0027178','2019-0027179','2019-0027180','2019-0027181','2019-0027182','2019-0027183'
MySql query is like so:
SELECT name, email, phone FROM persons WHERE id IN (?),
[fullString]
What's expected:
A json object containing the requested information like so:
[{name: "John", email: "john.doe#email.com", phone: "123456789"}, ... ]
Actual result:
An empty array like so:
[]
Investigation and Thoughts
I found out backticks were being added to the query string like so:
... WHERE id IN (`'2019-0027178','2019-0027179','2019-0027180','2019-0027181','2019-0027182','2019-0027183'`)
Actual actual main question:
Is there something I'm doing wrong or is there a proper way to do this?
EDIT!
So for a single question mark ie. ... WHERE id in (?), I get the empty object as stated above. But for two question marks ie. ... WHERE id IN (??), I get this error:
{
"code": "ER_BAD_FIELD_ERROR",
"errno": 1054,
"sqlMessage": "Unknown column ''2019-0027178','2019-0027179','2019-0027180','2019-0027181','2019-0027182','2019-0027183' in 'where clause'",
"sqlState": "42S22",
"index": 0,
"sql": "SELECT name, email, phone FROM persons WHERE id IN (`'2019-0027178','2019-0027179','2019-0027180','2019-0027181','2019-0027182','2019-0027183'`)"
}
Lets say you had a table called personfilter with the columns key and personid.
You then generate a unique key. For example 27. Then the following would do what you want:
INSERT INTO personfilter(key,personid)
values
(27, '2019-0027178'),
(27, '2019-0027179'),
(27, '2019-0027180'),
(27, '2019-0027181'),
(27, '2019-0027182'),
(27, '2019-0027183')
Then you could do the following select
SELECT name, email, phone
FROM persons
JOIN personfilter on personfilter.key = 27 and personfilter.personid = persons.id
Okay so I figured I could just 'prepare' the query before executing it.
~SOLUTION~
Instead of doing this let fullString= s.substr(0, s.length-1); before passing fullString as a parameter to the query string, I just did this:
let fullString= `SELECT name, email, phone FROM persons WHERE id IN (${s.substr(0, s.length-1)})`;
Then passed fullString in place of where the actual query was.
Thanks.

Can I find item on database with given array of string but using partial string?

I have model Product with name and category
On seed:
Product.create(name: "apple", category: "food")
Product.create(name: "biogesic", category: "medicine")
And a 2 dimensional array:
[[1, "tray of apple", 150.00], [1, "box of ballpen", 70.30]]
What I need is to get if the string inside the array contains or is on the table/database Product
Here's what I'm thinking but I'm lost:
isProduct = Product.where("name like ?", "%an apple%").first
Where "%apple%" is supposed to be the string on array, but with that code it is limited for 1 word only.
I don't need the product id, I just need it if it is on the Product table.
In a certain way, this can be accomplished with the Regular Expression Operator ~ for PostgreSQL and/or REGEXP for MySQL:
regex = array.flat_map { |_, sentence, _| sentence.split }.join('|')
Product.exists?(['name ~ ?', regex])
Product.exists?(['name REGEXP ?', regex])
Which produces:
SELECT 1 AS one FROM "products" WHERE (name ~ 'tray|of|apple|box|of|ballpen') LIMIT $1 [["LIMIT", 1]]
As it searches for the presence of every single word within the sentences tray of apple and/or box of ballpen.
So, in case you have a record like:
Product.new(name: 'tray of apple and box of ballpen')
It'll cover the query and return true.

MariaDB COLUMN_JSON query returns binary

I've been trying to use dynamic columns with an instance of MariaDB v10.1.12.
First, I send the following query:
INSERT INTO savedDisplays (user, name, body, dataSource, params) VALUES ('Marty', 'Hey', 'Hoy', 'temp', COLUMN_CREATE('type', 'tab', 'col0', 'champions', 'col1', 'averageResults'));
Where params' type was defined as a blob, just like the documentation suggests.
The query is accepted, the table updated. If I COLUMN_CHECK the results, it tells me it's fine.
But when I try to select:
"SELECT COLUMN_JSON(params) AS params FROM savedDisplays;
I get a {type: "Buffer", data: Array} containing binary returned to me, instead of the {"type":"tab", "col0":"champions", "col1":"averageResults"} I expect.
EDIT: I can use COLUMN_GET just fine, but I need every column inside the params field, and I need to check the type property first to know what kind of and how many columns there are in the JSON / params field. I could probably make it work still, but that would require multiple queries, as opposed to only one.
Any ideas?
Try:
SELECT CONVERT(COLUMN_JSON(params) USING utf8) AS params FROM savedDisplays
In MariaDB 10 this works at every table:
SELECT CONVERT(COLUMN_JSON(COLUMN_CREATE('t', text, 'v', value)) USING utf8)
as json FROM test WHERE 1 AND value LIKE '%12345%' LIMIT 10;
output in node.js
[ TextRow { json: '{"t":"test text","v":"0.5339044212345805"}' } ]

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