CONTAINS doesn't return any result - mysql

I know LIKE can be used instead of CONTAINS but CONTAINS is relatively faster as compared to LIKE. Here, the following query doesn't return me any result. Why?
Query:
SELECT CustomerName FROM members WHERE CONTAINS(Country, 'Mexico');
DATABASE:

MySQL Solution
select customername
from members
where match(country) against ('Mexico')
MS SQL Server Solution
Full text indexes aren't necessarily always populated after creation.
Use the following code to ensure the index updates:
ALTER FULLTEXT INDEX ON members SET CHANGE_TRACKING AUTO;
More info: https://msdn.microsoft.com/en-us/library/ms142575.aspx
Full example (including change tracking option on index creation rather than in a later alter statement):
use StackOverflow
go
create table myTable
(
id bigint not null identity(1,1)
constraint myTable_pk primary key clustered
, name nvarchar(100)
);
create fulltext catalog StackOverflow_Catalog;
create fulltext index
on myTable(name)
key index myTable_pk
on StackOverflow_Catalog
with change_tracking auto;
insert myTable
select 'Mexico'
union select 'London';
select *
from myTable
where contains(name,'Mexico');

Have you tried using in it might be even faster if it works in your case
SELECT CustomerName
FROM members
WHERE Country IN ('Mexico')
But in your case you may put %% in contains is actually faster then contain so just use this
SELECT CustomerName
FROM members
WHERE CONTAINS(Country, '"*Mexico"');

try this
If there is Full-Text Search Index on column Country.
SELECT CustomerName FROM members
WHERE CONTAINS(Country, 'Mexico');
Otherwise just do
SELECT CustomerName FROM members
WHERE Country LIKE N'%Mexico%';
there is a unicode character é, you need to prefix the string with N

Related

What changes shall we make in the table

I was asked below question in an interview which i could not answer.Could anyone please help.
A primary school teacher wants to store the first name,last name,date of birth,gender(0=female and 1=male) and home phone number of each of her pupils in a MySQL database.She came up with the following table definition:
CREATE TABLE pupil(
pupil_id INT NOT NULL AUTO_INCREMENT,
first_name CHAR(50),
last_name CHAR(50),
date_of_birth CHAR(50),
gender INT,
phone_number CHAR(50),
PRIMARY_KEY (pupil_id)
)ENGINE=MyISAM DEFAULT CHARSET=utf8;
she frequently runs the following queries
select * from pupil where pupil_id = 2;
select * from pupil where first_name = 'John';
select * from pupil where first_name = 'John' and last_name = 'Doe';
What changes will you make to this table? and why?
My answer would have been I would add two indexes. One for first_name and one for first_name, last_name.
If you frequently query according to the first name or the first and last names, it might be a good idea to index them:
CREATE INDEX pupil_names_ind ON pupil (first_name, last_name);
Having said that, you should really run a benchmark first. If the table has just a couple of hundreds of rows most of them will be caches anyway, and indexing it would be a wasted effort.
You just want one index
CREATE INDEX pupils_by_name ON pupil (first_name, last_name)
first query(by id) is optimised thanks to primary key
second query(by first name) is handled by pupils_by_name index, because it fits the index column orders starting from left hand side, if you would want to optimise a query by 'last_name' field, this index would't work because the order of columns in where clause must match an order of columns in and index starting from the left
thrid query fits the index pupils_by_name perfectly
in addition
date_of_birth CHAR(50) should be date
gender INT should be tinyint
I would create indexes on the first_name and last_name (in that order). it is important. more info here : http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
Then i would change the date_of_birth datatype to date
You should add an index in the table in the columns first_name and last_name.
Syntax : CREATE INDEX `ind` ON `table`(`col`);
This will make the searches on the indexed columns fast. Go through this article => When to use indexes? and MySQL's docs. Basically you use indexes on frequently searched items to boost the performance. But remember one thing : Too many indexes slow insertions into the table. So, an effective usage of indexes will definitely speed up a query.

different sequence same field in indexing are different

I have creat two indexes . The question is that [BCLIENT], [NAME] And in Second [NAME], [BCLIENT] Is that both will equal or it will work different manner , because i change the sequence in the indexing .
CREATE NONCLUSTERED INDEX [bclient] ON [dbo].[client]
(
[BCLIENT] ASC,
[NAME] ASC
)
GO
And Second index is Like this
CREATE NONCLUSTERED INDEX [RDATE] ON [dbo].[client]
(
[NAME] ASC,
[BCLIENT] ASC
)
No, they will not be equal, and will not act the same.
I always refer to the phone book example as a good reference for this.
Lets asy you have a query as follows
SELECT *
FROm PhoneBook
WHERE Surname = 'TADA'
and you have an index create as Surname, Name, the index would be properly used, but if the index was in the order Name, Surname the query engine would not be able to use the index, and would have to do an index scan/ table scan/ clustered index scan.

Is there a keyword to identify a PRIMARY column in a MySQL WHERE clause?

I have a situation where the column name "field1" and "field3" are not given to me but all the other data is. The request is coming in via a url in like: /table1/1 or /table2/3 and it is assumed that 1 or 3 represent the primary key. However, the column name may be different. Consider the following 2 queries:
SELECT * FROM table1 where field1 = 1 and field2 =2;
SELECT * FROM table2 where field3 = 3 and field4 =4;
Ideally, I'd like to perform a search like the following:
SELECT * FROM table1 where MYSQL_PRIMARY_COLUMN = 1 and field2 =2;
SELECT * FROM table2 where MYSQL_PRIMARY_COLUMN = 3 and field4 =4;
Is there a keyword to identify MYSQL_PRIMARY_COLUMN in a MySQL WHERE clause?
No, there's no pseudocolumn you can use to map to the primary key column. One reason this is complicated is that a given table may have a multi-column primary key. This is a totally ordinary way to design a table:
CREATE TABLE BooksAuthors (
book_id INT NOT NULL,
author_id INT NOT NULL,
PRIMARY KEY (book_id, author_id)
);
When I implemented the table data gateway class in Zend Framework 1.0, I had to write code to "discover" the table's primary key column (or columns) as #doublesharp describes. Then the table object instance retained this information so that searches and updates knew which column (or columns) to use when generating queries.
I understand you're looking for a solution that doesn't require this "2 pass process" but no such solution exists for the general case.
Some application framework environments attempt to simplify the problem by encouraging developers to give every table a single column primary key, and name the column "id" by convention. But this convention is an oversimplification that fails to cover many legitimate table designs.
You can use DESCRIBE (which is a synonym for EXPLAIN) to get information about the table, which will include the all column information.
DESCRIBE `table`;
You can also use SHOW INDEX to just get information about the PRIMARY key.
SHOW INDEX FROM `table` WHERE Key_name = 'PRIMARY'

Resort MySQL Table by Column Alphabetically

I have table containing settings for an application with the columns: id, key, and value.
The id column is auto-incrementing but as of current, I do not use it nor does it have any foreign key constraints. I'm populating the settings and would like to restructure it so they are alphabetical as I've not been putting the settings in that way, but reordering alphabetically would help group related settings together.
For example, if I have the following settings:
ID KEY VALUE
======================================
1 App.Name MyApplication
2 Text.Title Title of My App
3 App.Version 0.1
I would want all the App.* settings to be grouped together sequential without having to do an ORDER BY everytime. Anyway, thats the explanation. I have tried the following and it didn't seem to change the order:
CREATE TABLE mydb.Settings2 LIKE mydb.Settings;
INSERT INTO mydb.Settings2 SELECT `key`,`value` FROM mydb.Settings ORDER BY `key` ASC;
DROP TABLE mydb.Settings;
RENAME TABLE mydb.Settings2 TO mydb.Settings;
That will make a duplicate of the table as suggested, but won't restructure the data. What am I missing here?
The easy way to reorder a table is with ALTER TABLE table ORDER BY column ASC. The query you tried looks like it should have worked, but I know the ALTER TABLE query works; I use it fairly often.
Note: Reordering the data in a table only works and makes sense in MyISAM tables. InnoDB always stores data in PRIMARY KEY order, so it can't be rearranged.
Decided to make that an answer.
As I said in a comment to the initial answer, for you to achieve a long term effect you need to recreate the settings table with the key column as the PRIMARY KEY. Because as G-Nugget correctly said 'InnoDB always stores data in PRIMARY KEY order'.
You can do that like this
CREATE TABLE settings2
(`id` int NULL, `key` varchar(64), `value` varchar(64), PRIMARY KEY(`key`));
INSERT INTO settings2
SELECT id, `key`, `value`
FROM settings;
DROP TABLE settings;
RENAME TABLE settings2 TO settings;
That way you get your order intact after inserting new records.
And if you don't need the initial id column in settings table it's a good time to ditch it.
Here is working sqlfiddle
Disclaimer: Personally I would use ORDER BY anyway

Removing doublettes

I'm trying to remove doublettes (sometimes triplettes, unfortunately!) from a MySQL table. My issue is that the only unique data available are the primary key, so in order to identify doublettes, you have to take account all the columns.
I've managed to identify all records that have doublettes and copied them along with their doublettes (including their primary keys) to the table temp. The source table is called translation and it has an integer primary key with the name TranslationID. How do I move on from here? Thanks!
edit Available columns are:
TranslationID
LanguageID
Translation
Etymology
Type
Source
Comments
WordID
Latest
DateCreated
AuthorID
Gender
Phonetic
NamespaceID
Index
EnforcedOwner
The duplicity issue resides with the rows with the Latest column assigned 1.
edit #2 Thank you, everyone for your time! I've solved the problem by using WouterH's answer, resulting in the following query:
DELETE from translation USING translation, translation as translationTemp
WHERE translation.Latest = 1
AND (NOT translation.TranslationID = translationTemp.TranslationID)
AND (translation.LanguageID = translationTemp.LanguageID)
AND (translation.Translation = translationTemp.Translation)
AND (translation.Etymology = translationTemp.Etymology)
AND (translation.Type = translationTemp.Type)
AND (translation.Source = translationTemp.Source)
AND (translation.Comments = translationTemp.Comments)
AND (translation.WordID = translationTemp.WordID)
AND (translation.Latest = translationTemp.Latest)
AND (translation.AuthorID = translationTemp.AuthorID)
AND (translation.NamespaceID = translationTemp.NamespaceID)
You can remove duplicates without temporary table or subquery. Delete all rows that have the same data but a different TranslationID
DELETE from translation USING translation, translation as translationTemp
WHERE (NOT translation.TranslationID = translationTemp.TranslationID)
AND (translation.LanguageID = translationTemp.LanguageID)
AND (translation.Translation = translationTemp.Translation)
AND (translation.Etymology = translationTemp.Etymology)
AND // compare other fields here
Create a SELECT statement with your current SELECT as a sub-select, so that you can return a col of IDs that should be removed. Then apply that SELECT in a DELETE FROM statement.
Example (pseudo code):
SELECT1 = SELECT ... AS temp; # the table you have right now
SELECT2 = SELECT TranslationID FROM (SELECT1)
Final query will look like this:
DELETE FROM table_name WHERE TranslationID IN (SELECT2);
You just need to insert the SELECT with sub-select in the final query.
Top stop duplicates in future you can change your engine to the InnoDB engine like this:
ALTER TABLE table_name ENGINE=InnoDB;
Then add a Unique constraint to the TranslationID field.
If the doublettes/triplettes are identical except for the primary key, then you can select all records from temp which are identical to another except for having a larger primary key than that other; this will give you temp w/ the record w/ the minimum key for each doublet/triplette. You can then delete these records from translation.
Instead of identifying the lines that aren't unique, I would try to copy the valid data to a new table, and then remove the old one and replace it by this new, cleaned table.
I can see of two ways:
Using the DISTINCT keyword in your SQL query (source);
Using a GROUP BY statement on all columns (source).