MYSQL Auto increment categorized by field - mysql

Is there anyway i can set the auto increment value in MYSQL to increase itself by grouping itself by a field id? Such as
Shop_id | AI_Value
-------------------
1 | 1
1 | 2
2 | 1
3 | 1
1 | 3
Currently, im running a query to get the last row, and then insert by adding +1 to the value, which i assume is highly inefficient, and will have potential flaws, such as duplicated values

you can use an utility table that is made just to store one progressive number. When you retrieve next progressive number you must lock the table, get the number, add +1 and store it.

MyISAM tables support just that. You can have the AUTO_INCREMENT on a second column in the index, and it will increment only as per change to the first column.
Alas, this means you will have to use MyISAM, which is a downside in itself...

Related

add int value of float to increase selecting speed

If I have a large table with floating numbers, can it help in reading speed if I add a column that represent the int value of each float? maybe if the int value will be an index, then when I need to select all the floats that starts with certain int it will "filter" the values that are surely not necessary?
For example if there are 10,000 numbers, 5000 of which begin with 14: 14.232, 14.666, etc, is there an sql statement that can increase the selecting speed if I add the int value column?
id | number | int_value |
1 | 11.232 | 11 |
2 | 30.114 | 30 |
3 | 14.888 | 14 |
.. | .. | .. |
3005 | 14.332 | 14 |
You can create a non clustered index on number column itself. and when selecting the data from table you can filtered out with like operator. No need of additional column,
Select * from mytable
where number like '14%'
First of all: Do you have performance issues? If not then why worry?
Then: You need to store decimals, but you are sometimes only interested in the integer part. Yes?
So you have one or more queries of the type
where number >= 14 and number < 15
or
where truncate(number, 0) = 14
Do you already have indexes on the number? E.g.
create index idx on mytable(number);
The first mentioned WHERE clause would probably benefit from it. The second doesn't, because when you invoke a function on the column, the DBMS doesn't see the relation to the index anymore. This shows it can make a difference how you write the query.
If the first WHERE clause is still too slow in spite of the index, you can create a computed column (ALTER TABLE mytable ADD numint int GENERATED ALWAYS AS truncate(number, 0) STORED), index that, and access it instead of the number column in your query. But I doubt that would speed things up noticeably.
As to your example:
if there are 10,000 numbers, 5000 of which begin with 14
This is not called a large table, but a small one. And as you'd want half of the records anyway, the DBMS would simply read all records sequentially and look at the number. It doesn't make a difference whether it looks at an integer or a decimal number. (Well, some nanoseconds maybe, but nothing you would notice.)

Most efficient, scalable mysql database design

I have interesting question about database design:
I come up with following design:
first table:
**Survivors:**
Survivor_Id | Name | Strength | Energy
second table:
**Skills:**
Skill_Id | Name
third table:
**Survivor_skills:**
Surviror_Id |Skill_Id | Level
In first table Survivors there will be many records and will grow from time to time.
In second table will be just few skills which can survivors learn (for example: recoon (higher view range), sniper (better accuracy), ...). Theese skills aren't like strength or energy which all survivors have.
Third table is the most interesting, there survivors and skills join together. Everything will work just fine but I am worried about data duplication.
For example: survivor with id 1 will have 5 skills so first table would look like this:
// survivor_id | level_id | level
1 | 1 | 2
1 | 2 | 3
1 | 3 | 1
1 | 4 | 5
1 | 5 | 1
First record: survivor with id 1 has skill with id 1 on level 2
Second record ...
Is this proper approach or should I use something different.
Looks good to me. If you are worried about data duplication:
1) your server-side code should be gear to not letting this happen
2) you could check before inserting if it already exists
3) you could use MYSQL: REPLACE INTO - this will replace duplicate rows if configure proerply, or insert new ones (http://dev.mysql.com/doc/refman/5.0/en/replace.html)
4) set a unique index on columns where you want only unique rows, e.g. level_id, level
I concur with the others - this is the proper approach.
However, there is one aspect which hasn't been discussed: the order of columns in the composite key {Surviror_Id, Skill_Id}, which will be governed by the kinds of queries you need to run...
If you need to find skills of the given survivor, the order needs to be: {Surviror_Id, Skill_Id}.
If you need to find survivors with the given skill, the order needs to be: {Skill_Id, Surviror_Id}.
If you need both, you'll need both the key (and the implied index) on {Surviror_Id, Skill_Id} and an index on {Skill_Id, Surviror_Id}1. Since InnoDB tables are clustered, accessing Level through that secondary index requires double-lookup - to avoid that, consider using a covering index {Skill_Id, Surviror_Id, Level} instead.
1 Or vice-verse.

MySQL auto increment ID based on the values of two other columns

Is there a way to auto increment the id field of my database based on the values of two other columns in the inserted row?
I'd like to set up my database so that when multiple rows are inserted at the same time, they keep their tracknumber ordering. The ID field should auto increment based firstly on the automatically generated timestamp field, and then secondly the tracknumber contained within that timestamp.
Here's an example of how the database might look:
id | tracknumber | timestamp
________________________________________
1 | 1 | 2014-03-31 11:35:17
2 | 2 | 2014-03-31 11:35:17
3 | 3 | 2014-03-31 11:35:17
4 | 1 | 2014-04-01 09:10:14
5 | 2 | 2014-04-01 09:10:14
I've been reading up on triggers but not sure if that's appropriate here? I feel as though i'm missing an obvious function.
This is a bit long for a comment.
There is no automatic way to do this. You can do it with triggers, if you like. Note the plural, you will need triggers for insert, update, and delete, if you want the numbering to remain accurate as the data changes.
You can do this one the query side, if the goal is to enumerate the values. Here is one method using a subquery:
select t.*,
(select count(*) from table t2 where t2.timestamp = t.timestamp and t2.id <= t.id
) as tracknumber
from table t;
The performance of this might even be reasonable with an index on table(timestamp, id).
If the data is being created once, you can also populate the values using an update query.
If you are inserting them in one transaction and or script, then sort the data yourself in the server side according to these two fields (assuming you create timestamp on server side too because that would seem logical) and then insert the rows one after another. I don't think it is necessary to overthink this and look for a difficult approach in the database. Database will still be inserting rows one after another, not all at once so there is no way it will know that it needs to do some kind of sorting beforehand. It is you who has to do it.

Store multiple values in a single cell instead of in different rows

Is there a way I can store multiple values in a single cell instead of different rows, and search for them?
Can I do:
pId | available
1 | US,UK,CA,SE
2 | US,SE
Instead of:
pId | available
1 | US
1 | UK
1 | CA
1 | SE
Then do:
select pId from table where available = 'US'
You can do that, but it makes the query inefficient. You can look for a substring in the field, but that means that the query can't make use of any index, which is a big performance issue when you have many rows in your table.
This is how you would use it in your special case with two character codes:
select pId from table where find_in_set('US', available)
Keeping the values in separate records makes every operation where you use the values, like filtering and joining, more efficient.
you can use the like operator to get the result
Select pid from table where available like '%US%'

can a row in mysql reference itself?

Can a row in mysql reference itself in a sub-query?
test_table
id | field 1 | field 2 | field 3
1 | 25 | 10 | average of field 1 and 2
is it possible to have column 3 reference itself?
Thanks.
You can set row 3 equal to the average of columns 1 and 2 at any point, but that value will only be true for the values of those columns at that point in time.
If you're looking for an Excel-style field that automatically updates the column when you change a different column, then you'll want to use a trigger that will update the third column when either the first or second is updated.
In the case you want the value to be returned in your select statement, use this:
SELECT id, field1, field2, (CAST((field1 + field2) as DECIMAL)/2) AS 'field 3'
FROM tablename
Casting the sum into decimal will prevent losing precision in your average.
For a simple calculation like that, wouldn't you rather have it referenced in a php function instead? Storing it in the database is an unnecessary use of space.