Search wildcard multiple columns in Rails using one param - mysql

Using Rails 3.2. I have the following table:
name address
=======================================
Hilton Hotel New York, USA
Hilton Hotel Paris, France
Mandarin Hotel Chicago, USA
Le Meridien Hotel New York, USA
and the following query:
term = "%#{params[:term]}%"
shops = Shop.limit(10).where("name LIKE ? OR address like ?", term, term)
My expected result is this:
Search - "Hilton"
Result - "Hilton Hotel, New York, USA"; "Hilton Hotel, Paris, France"
Search - "Hilton USA"
Result - "Hilton Hotel, New York, USA"
Search - "New York"
Result - "Hilton Hotel, New York, USA"; "Le Meridien Hotel, New York, USA"
How should I rewrite my query?
Thanks.

You could use MySQL's MATCH AGAINST. There's no direct support in Rails, but you can always roll your own custom query in Rails using
YourModel.find_by_sql("SELECT ... WHERE MATCH(...) AGAINST(...)")
or a bit more Rails style (have not tested this):
YourModel.where("MATCH(...) AGAINST(...)")
For more information, have a look here: http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html
EDIT:
I'd split the input string by space, comma, dot, etc. and then use MATCH AGAINST to get all results. So if you have this table:
col1 | col2
-----------
row1: a c | a
row2: a d | b e
row3: b e | a d
row4: b | b c
And the user types a as input. You should do
MATCH(col1, col2) AGAINST ('a')
This will return:
row1: 'a c', 'a'
row2: 'a d', 'b e'
row3: 'b e', 'a d'

I use another workaround for this.
I create another column for_autocomplete and concatenate the name and address into it. Every time a record is created/updated, it will create/update for_autocomplete accordingly. Then I just search through the for_autocomplete column.

Related

How to purposely duplicate specific rows in SELECT statement?

I want to duplicate a specific teacher so that they appear twice in the output of a SELECT statement.
Teacher
Grade
District
Mr. Smith
3rd
West
Mrs. John
4th
South
Mr. Cameron
2nd
North
Mr. Cameron
2nd
North
Kirk Horn
1st
West
Desired result, after duplicating 'Mr. Cameron':
Teacher
Grade
District
Mr. Smith
3rd
West
Mrs. John
4th
South
Mr. Cameron
2nd
North
Mr. Cameron
2nd
North
Mr. Cameron
2nd
North
Mr. Cameron
2nd
North
Kirk Horn
1st
West
What would a SELECT statement look like - without creating a new a table?
I want to do something like this but without the INSERT:
https://dba.stackexchange.com/questions/142414/easiest-way-to-duplicate-rows
If the table is big, and the filter is not selective and backed by an index, then this "trick" avoids a second sequential scan over the table - using PostgreSQL:
SELECT t.* -- or your list of columns
FROM test t
, generate_series(1, CASE WHEN t.teacher = 'Mr. Cameron' THEN 2 ELSE 1 END);
fiddle
It's short syntax for a LATERAL join. See:
What is the difference between a LATERAL JOIN and a subquery in PostgreSQL?
fiddle
If you need more copies, just replace '2' above.
Postgres has a hard time estimating the number of rows to expect with this construct, which may confuse query planning. Stu's variant (doing the same) is slightly more expensive, but easier to estimate for query planning. Syntax needs to be adapted for Postgres:
SELECT teacher, grade, district
FROM test t
JOIN LATERAL (VALUES (1),(2)) x(v) ON v = 1 OR teacher = 'Mr. Cameron';
fiddle
You could use UNION ALL
select Teacher,Grade,District
from test
union all
select Teacher,Grade,District
from test
where Teacher='Mr. Cameron'
order by Teacher;
https://dbfiddle.uk/rBpSL8NW
If you want to force/predict how many duplicate values for Mr. Cameron you will add ,try below query which add only one duplicate value limit 1
(select Teacher,Grade,District
from test
)
union all
(
select Teacher,Grade,District
from test
where Teacher='Mr. Cameron'
limit 1
);
https://dbfiddle.uk/uUX5QD3F

MySql - Select from a string concatenated with a comma

Suppose I have this MySql table:
id
name
city
1
John
NYC
2
Albert
London
3
Joanna
Paris
4
Mike
LA
5
Norton
São Paulo
6
Pedro
Rio de Janeiro
7
August
Chicago
8
Carol
Miami
So I get this string and I would like to filter people with these ids:
"1,3,6,8"
Sometimes the string I got is different: "1,5,4" or "3,6,5,8,1" etc.
Any idea how to achieve this?
You would use a WHERE IN (...) construct in your query:
SELECT *
FROM yourTable
WHERE id IN (1, 3, 6, 8);
#Vanderlei based on your comment I will suggest not using a subquery, but a join because it performs much faster.
select products_table.id,products from products_table
inner join table_people
on products_table.id=table_people.id
WHERE table_people.city = 'London';
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/61

Query for finding similar interests together

Name Place visited
Ash New york
Bob New york
Ash Chicago
Bob Chicago
Carl Chicago
Carl Detroit
Dan Detroit
Above is the sample table. The output should be two names who visited place together. I.e. the output should be Ash and Bob since the places visited by Ash also visited by Bob.
Output:
Name1 Name2
Ash Bob
What is a query for this using MySQL or even relational algebra?
The simplest method is to use group_concat(). Assuming no duplicates,
select places, group_concat(names) as names
from (select name, group_concat(place order by place) as places
from t
group by name
) t
group by places
having count(*) > 1;
This will return all the names with exactly the same places on a single row. The names will be in a comma-delimited list.

How to get only one value from data base colum that has multiple same values? [duplicate]

This question already has an answer here:
How to output table results by using cfoutput group by date?
(1 answer)
Closed 7 years ago.
I'm working on outputting values from data base in the table. My table has 5 columns: Date, FirstName, LastName, City, State. Here is example of my data base table:
DateMeeting FirstName LastName City State
2015-12-11 Mike Johns Dallas TX
2015-12-11 John Cook Dallas TX
2015-12-11 Nick Roberts Dallas TX
2015-12-11 Oliver Ryan New York NY
2015-12-11 Michael Best New York NY
2015-12-11 David Holmes New York NY
So I want to have output table that will display just one date for multiple records. I tried to use DISTINCT on the date and that works fine but if I include my WHERE clause for City and State my query breaks. Also I tried to use GROUP BY but same problem, I can get Date values only once as long as I do not include other columns. In this case I need all columns but my Date value only once. Here is my query that I use:
Select Distinct(DateMeeting),FirstName, LastName, City, State
From Customers
Where City = 'Dallas'
and State = 'TX'
This query does not work with all columns that I have in my select, only if I run DISTINCT(DateMeeting). I would like to output my values in the table to look like this:
Date First Name Last Name City State
Mike Johns Dallas TX
John Cook Dallas TX
Nick Roberts Dallas TX
2015-12-11 Oliver Ryan New York NY
Michael Best New York NY
David Holmes New York NY
If anyone knows how this can be done please let me know. Thank you.
Each layer in the technology stack has its strengths and weaknesses.
As for mysql, do not turn it into a report engine as described with blank date columns except for one per date somewhere in the middle of a date chunk as shown. Subsequent dates as ordered will get muddled and confused.
True, one could use slightly interesting mysql variables and dump it just on the first row of a chunk. But for what.
Play to mysql's strengths, return all the data. And have the front-end (coldfusion or whatever), deal with the reporting features you desire for the output.

Search multiple tables in mysql

I have a table structured like this (not the actual data or fields, but the same structure applies):
ID | City Field2 Field 3
-------------------------------
1 New York Ohio data
2 Cincinnati data data
3 Los Angeles data Ohio
4 Cleveland data data
Then there's a second table something like this (again, not the actual data)
City State
-------------------------------
Los Angeles California
New York New York
Cincinnati Ohio
Cleveland Ohio
Houston Texas
etc.
I have a php web page that allows users to search the database; when they do, it will automatically print (in my example) the corresponding state from the second table after the city.
However, if the user searches for "Ohio", it should return all four records, even though "Ohio" doesn't exist in the first table. It looks like I'd have to run multiple queries - find the search term in the first table, find it again in the second table, and then search for column 1 of the second table in the first table (and then join the results). Is there an easier way to do that? (I'm fairly new to MySQL.)
Have you tried using a UNION?
SELECT City FROM table1 WHERE Field2 = 'Ohio' OR Field3 = 'Ohio'
UNION ALL
SELECT City FROM table2 WHERE State = 'Ohio'
It would be helpful to see what your query looks like.