Optimize query many field mysql - mysql

I'm confused about how to chose best index for my table:
Have this table:
Hotel
-has_1
...
-has-5
-nota_AVG
-nota_1
-nota_2
-nota_3
and this
Nota_hotel
-nota_1
-nota_2
-nota_3
-id_hotel
Field with name "nota_*" from hotel is update from a trigger on table Nota_hotel and this field changed frequently.
My need do some query like
select * from hotel where has_X = true or has_Y=true order by nota_Z
where my clause "WHERE" can have 1 has_X or many has_* fields in query depend on what checkbox is selected.
I want know what is best practice to put index, add for every field "nota_" a index and for fields "has_" create a single index(has_1,...,has_5) or add for every field "has_" a index too, and if have this much index is possible to strangle my MySQL server ?
create table hotel(
id int primary key auto_increment,
nume varchar(255),
index hotel_nume_index(nume),
nume_oras varchar(100),
nume_zona varchar(100),
nume_tara varchar(100),
foreign key (nume_oras,nume_zona,nume_tara) references oras(nume,nume_zona,nume_tara) ON DELETE CASCADE,
descriere text,
stele int,
map_x double,
map_y double,
has_sauna TINYINT(1),
has_piscina TINYINT(1),
has_parcare TINYINT(1),
has_restaurant TINYINT(1),
has_fitness TINYINT(1),
distanta_obiectiv double,
code_api1 varchar(255),
code_api2 varchar(255),
code_api3 varchar(255),
intern TINYINT(1),
nota_hotel double,
nota_restaurant double,
nota_locatie double,
nota_conditii double,
nume_comision varchar(100),
foreign key (nume_comision) references comision(nume)
);
create table nota_hotel(
fb_id varchar(100),
data DATETIME,
nota_restaurant double,
nota_locatie double,
nota_conditi double,
comentariu text,
nume_user varchar(255),
id_hotel int,
foreign key (id_hotel) references hotel(id) ON DELETE CASCADE
);
Here is full definition

this is a work in progress answer. will add to it.
let's say you have 5 has_ columns, like has_restaurant, has_pool, has_pool and searches are on true types like before, as in 'it is true that it has a pool'
for starters, convert them into one column using powers of 2. let us call that hasX and its column value is a bit-wise OR of the below (that are not columns)
has_restaurant (2^0) 1
has_pool (2^1) 2
has_wifi (2^2) 4
has_piscina (2^3) 8
has_sauna (2^4) 16
so if the hotel has wifi and sauna then the hasX column will contain (at least) the bits turned on with value 20, but could contain a value of 21 (has a restaurant too). but the search was on 'i want wifi and sauna' so it finds the 21 too. it is a mask
so at this point we have added one index to hotel, on column hasX
Edit
I just bombed on this notion as i assumed i could craft a bit-wise search and that seems quite impossible after reading about it. The following seems to be the best work-up
CREATE TABLE hotel (
hotel_id int primary key auto_increment PRIMARY KEY,
/* some more fields... */
);
CREATE TABLE hotel_flags (
flag_id TINYINT UNSIGNED NOT NULL
, description VARCHAR(100) NOT NULL
, PRIMARY KEY (flag_id)
);
**the following is the intersect table**
CREATE TABLE hotel_flags_intersect (
hotel_id int not null
, flag_id TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (hotel_id, flag_id)
, UNIQUE INDEX reverse_pk (flag_id, hotel_id)
);
humbly borrowed from http://forums.mysql.com/read.php?24,35318,35640#msg-35640

Related

How to create tables with columns that have range in MySQL?

I want to create a table for the following:
One pokemon must have and can only have one trainer.
One pokemon may evolve into many other pokemons.
The pokemon name has a maximum of 50 characters and can not be
blank.
The dex number has 3-numeric-digit and can not be blank.
The pokemon height is a whole number and ranges [0, 1,000] cm
inclusive.
The pokemon weight ranges [0.00, 1,000.00] kg inclusive.
The pokemon color has a maximum of 20 characters.
The pokemon type has a maximum of 15 characters. If an INSERT
doesn't list the pokemon type value, it should default to Grass
I am stuck specifically on number 5. How do I apply that to my table? Also, another question is how do I apply numbers 5-6 and 8 also? How can I also assign the EvolvedFrom as one of the Foreign Keys? I don't know where to refrence it. I am a little bit confused, so please help. Thank you so much.
Table Reference
ERD of the table to be created
This is my sample code that I have created:
CREATE TABLE pokemon(
pokemonId int,
pokemonDexNum int(3) NOT NULL,
pokemonName varchar(50) NOT NULL,
pokemonHeightCm int unsigned,
CONSTRAINT CHK_pokemonHeightCm CHECK (pokemonHeightCm <= 1000)
pokemonWeightKg int NOT NULL,
pokemonColor varchar(50),
pokemonType varchar(50),
trainerId int NOT NULL,
evolvedFrom varchar(50),
PRIMARY KEY (pokemonId),
FOREIGN KEY (trainerId) REFERENCES trainer(trainerId),
FOREIGN KEY (evolvedFrom) REFERENCES pokemon(evolvedInto) --THIS LINE IS INCORRECT. HELP--
);
Try to include a constrain as below.
CREATE TABLE pokemon(
pokemonHeightCm int() NOT NULL,
CONSTRAINT pokemonHeightCm_Ck CHECK (pokemonHeightCm BETWEEN 0 AND 1000),
... and the rest
Try the below, I haven't tested the syntaxes:
CREATE TABLE pokemon(
pokemonId int ,
pokemonDexNum int(3) NOT NULL, #rule 4
pokemonName varchar(50) NOT NULL, #rule 3
pokemonHeightCm int NOT NULL, CONSTRAINT CHK_pokemonHeightCm CHECK (pokemonHeightCm <= 1000), #rule 5
pokemonWeightKg decimal NOT NULL, CONSTRAINT CHK_pokemonWeightKg CHECK (pokemonWeightKg <= 1000.00), #rule 6
pokemonColor varchar(20), #rule 7
pokemonType varchar(15) NOT NULL DEFAULT 'Grass', #rule 8
trainerId int NOT NULL,
evolvedFrom int,
PRIMARY KEY (pokemonId), #rule 1
FOREIGN KEY (trainerId) REFERENCES trainer(trainerId), #rule 1
FOREIGN KEY (evolvedFrom) REFERENCES pokemon(pokemonId) #rule 2
);

Syntax error on adding multiple indexes on Table Creation mysql

I am trying to run a CREATE TABLE script which has multiple INDEXES.
CREATE TABLE IF NOT EXISTS Equipment (
EquipmentID BIGINT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
Type VARCHAR(255) NOT NULL,
Make VARCHAR(255),
Model VARCHAR(255),
Description VARCHAR(255),
OperationNotes TEXT,
Damaged BOOLEAN DEFAULT 0,
PRIMARY KEY (EquipmentID),
INDEX ('EquipmentID'),
INDEX('Type'),
INDEX('Model'),
INDEX('Description')
INDEX('Damaged')
);
However I get a syntax error:
"(" is not valid at this position for this server version
On line:
INDEX ('EquipmentID'),
Single quote (') denote string literals. When referring to object names (such as columns), you shouldn't use single quotes. Remove them, and you should be OK. Also, note that a primary key implicitly creates an index, so you don't need to explicitly create an index on EquipmentID:
CREATE TABLE IF NOT EXISTS Equipment (
EquipmentID BIGINT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
Type VARCHAR(255) NOT NULL,
Make VARCHAR(255),
Model VARCHAR(255),
Description VARCHAR(255),
OperationNotes TEXT,
Damaged BOOLEAN DEFAULT 0,
PRIMARY KEY (EquipmentID),
INDEX (Type),
INDEX (Model),
INDEX (Description),
INDEX (Damaged)
);

Declare variable MySQL trigger and create table using that variable

I have a event in which I am storing a string in a variable. Now I want to use that variable to create a new table. Everytime my event runs it creates table with the name of "mon". What is I am doing wrong ?
BEGIN
DECLARE onlyweek INT;
DECLARE mon VARCHAR(20);
SET #mon = "rehan";
CREATE TABLE mon(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
capacity INT NOT NULL
);
END
Because you use mon instead of #mon. And even then it wont work because you need dynamic SQL for that.
But what is even more important:
Don't do that!
Don't create a table on the fly. Table designs should be static. That smells like a big design flaw.
This is a design mistake. For example, you need to make report for the year. In your design you have to join 12 tables and where-s how to join. And this is very slow.
Better design is creating 2 tables - "months" and "reporting_periods" with foreign key to table 'months'. This way when you need year report - you join only 2 tables by ID with "where".
Table 'months' can be filled once a year using same mysql events.
Then use mysql "stored procedure" (and mysql event) for periodic insert into reporting_period with month id. Months` names can include year as "bad way" or have the field 'year' = 'better one'.
CREATE TABLE months(
id int auto_increment,
name varchar(10),
number int not null,
year int not null,
constraint monthes_pk
primary key (id)
);
and reporting_period
CREATE TABLE reporting_period(
id INT auto_increment,
period_id INT NOT NOT,
capacity INT NOT NULL,
constraint `reporting_period_pk`
primary key (id),
constraint `reporting_period__fk`
foreign key (period_id) references months (id)
);
More about DB design: normalization

modeling issue with field with 4 values (1 or more)

lets say I have an account object in my application, which currently represented as:
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (accountId)
);
Now, Account object need to also have Solution field...and Status have 4 different possible values:
Solution1, Solution2, Solution3, Solution4
What would be the right way to represent it in the database?
Account can have few statuses, and status can have few accounts...
So at first I thought create in the db table of Solutions and than have another table to hold the relationship, but its seems too complicated for a field that have only 4 possible values...
Create a junction table to represent the relationships between accounts and solutions:
CREATE TABLE account_solution (
accountId int NOT NULL,
solutionId int NOT NULL
PRIMARY KEY (accountId, solutionId)
)
For your solution table, since there are only 4 values, you might be able to take advantage of MySQL's enum type, e.g.
CREATE TABLE solution
solutionId int NOT NULL PRIMARY KEY,
status ENUM('Solution1', 'Solution2', 'Solution3', 'Solution4')
);
You can use set Mysql SET type
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
status set('Solution1','Solution2','Solution3','Solution4') NOT NULL,
PRIMARY KEY (accountId)
);
And if you want to select a specific status
SELECT *
FROM `Account`
WHERE FIND_IN_SET( 'Solution2', `status` ) >0

MySQL - add data into 2 tables and 1 has foreign key

I'm a totally MySQL newcomer. Sr if my question is quite obvious. I got 2 tables
CREATE TABLE tbl_addresses(
PK_ADDRESS_ID int NOT NULL AUTO_INCREMENT,
house_number int NOT NULL,
street varchar(35),
district varchar(35),
city varchar(35),
postcode varchar(8),
PRIMARY KEY (PK_ADDRESS_ID)
);
CREATE TABLE tbl_people(
PK_PERSON_ID int NOT NULL AUTO_INCREMENT,
title varchar(6) NOT NULL, # Master / Mister therefor 6 is max
forename varchar(35) NOT NULL,
surname varchar(35) NOT NULL,
date_of_birth DATE NOT NULL,
contact_number varchar(12) NOT NULL,
FK_ADDRESS_ID int NOT NULL,
PRIMARY KEY (PK_PERSON_ID),
FOREIGN KEY (FK_ADDRESS_ID) REFERENCES tbl_addresses (PK_ADDRESS_ID)
);
and I'm trying to import data into these tables from Java using below syntaxes
INSERT INTO tbl_addresses (house_number,street,district,city,postcode) VALUES ('1','abc','','abc','abc');
INSERT INTO tbl_people (title,forename,surname,date_of_birth,contact_number) VALUES ('Mr','Tri ','Nguyen','1991-1-1','0123456789');
I got an error Field 'FK_ADDRESS_ID'doesn't have a default value and data actually goes into tbl_addresses but not tbl_people. Am I missing anything? Thanks in advance!
This error is being caused by that you labelled the FK_ADDRESS_ID field in the tbl_people table as NOT NULL, yet you are trying to do an INSERT without specifying a value for this column.
So something like this would work without error:
INSERT INTO tbl_people (title, forename, surname, date_of_birth,
contact_number, FK_ADDRESS_ID)
VALUES ('Mr', 'Tri', 'Nguyen', '1991-1-1', '0123456789', 1);
You could also specify a default value for FK_ADDRESS_ID (the error message you got alluded to this). Here is how you could adda default value:
ALTER TABLE tbl_people MODIFY COLUMN FK_ADDRESS_ID int NOT NULL DEFAULT 1
But because FK_ADDRESS_ID is a key into another table, the value should really be based on the primary key in tbl_addresses.
The fact that you are using a foreign key isn't the reason that you are getting this error. Let's take a look at your column definition.
FK_ADDRESS_ID int NOT NULL,
This is not null but does not a default. Now a look at your insert statement
INSERT INTO tbl_people (title,forename,surname,date_of_birth,contact_number)
FK_ADDRESS_ID isn't in your column list but it cannot be null and doesn't have a default so what can mysql do? Produce an error of course.
The best bet is to define that column as nullable.
Let's revisit the foreign key constraint.
FOREIGN KEY (FK_ADDRESS_ID) REFERENCES tbl_addresses (PK_ADDRESS_ID)
What this really says is that if you asign a value to FK_ADDRESS_ID that value should be present in PK_ADDRESS_ID column in tbl_address
as a side note, it's customary to use lower case for table/column names.