mysql script variables and max function-2 - mysql

I had asked a question here on how to get a sql function(max) result into a #variable and how to use it. The answer I got was very straightforward and useful(tanx to the responder: Tom Mac). No I am using the same mechanism in my program and I get an unacceptable result that I'll explain here:
Please Have a look at my mysql console and everything is self explanatory. Even my question :) :
> mysql> select max(command_idx) into #max_command_idx from command;
> Query OK, 1 row affected (0.00 sec)
Now use the variable for the first time:
mysql> insert into command(controller_idx,subcontroller_idx,command_idx,controller_id, subcontroller_id,code,status,type,plan_name,timetable_id,offset,ctime,user_name,result) values
(0,0,#max_command_idx+1,'937','SUB0','SMS',0,'CONFIG','NA','NA',0,NOW(),'admin',0);
Query OK, 1 row affected (0.00 sec)
Now use the variable for the second time for another table:
> mysql> insert into
> csmslist(controller_idx,subcontroller_idx,command_idx,csmslist_idx,phone)
> values(0,0,#max_command_idx+1,0,'+60127929022');ERROR 1048 (23000):
> Column 'command_idx' cannot be null
.......................................................................
My QUESTION:
would you kindly tell me why I get this error?
THANK YOU
.......................................................................
more information on my tables:
mysql> desc csmslist;
+-------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+---------+-------+
| controller_idx | int(11) | NO | PRI | NULL | |
| subcontroller_idx | int(11) | NO | PRI | NULL | |
| command_idx | int(11) | NO | PRI | NULL | |
| csmslist_idx | int(11) | NO | PRI | NULL | |
| phone | varchar(24) | YES | | NULL | |
+-------------------+-------------+------+-----+---------+-------+
5 rows in set (0.01 sec)
mysql> desc command;
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| controller_idx | int(11) | NO | PRI | NULL | |
| subcontroller_idx | int(11) | NO | PRI | NULL | |
| command_idx | int(11) | NO | PRI | NULL | auto_increment |
| controller_id | varchar(24) | YES | | NULL | |
| subcontroller_id | varchar(24) | YES | | NULL | |
| code | varchar(12) | YES | | NULL | |
| status | int(11) | YES | | NULL | |
| type | varchar(24) | YES | | NULL | |
| plan_name | varchar(24) | YES | | NULL | |
| timetable_id | varchar(24) | YES | | NULL | |
| offset | int(11) | YES | | NULL | |
| ctime | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| user_name | varchar(80) | YES | | NULL | |
| result | int(11) | YES | | NULL | |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
14 rows in set (0.01 sec)

The command table has an auto_increment, when you set the column to null (which is what you are doing, despite what you think you are doing), it just does an auto increment on it.
The csmslist table has no auto increment so inserting null fails.
Do this instead:
insert into csmslist(controller_idx,subcontroller_idx,command_idx,csmslist_idx,phone)
values(0,0,LAST_INSERT_ID(),0,'+60127929022');ERROR 1048 (23000):
Column 'command_idx' cannot be null
And in the insert to command just make the column NULL and let the database do its thing for you automatically.
It could be the command table is empty, so it's returning NULL for the max.
BTW instead of using a variable you can put that query right in there:
insert into csmslist(controller_idx,subcontroller_idx,command_idx,csmslist_idx,phone)
values(0,0,(select max(command_idx) from command),0,'+60127929022');ERROR 1048 (23000):
Column 'command_idx' cannot be null

Related

Very slow select but uniq key, is there way to improve?

On my authorization, i was looking user by his social id:
select * from users where yandex_id = 65250508;
And result is very bad: 1 row in set (11.25 sec)
Count of this table:
select count(id) from users;
+-----------+
| count(id) |
+-----------+
| 1852446 |
+-----------+
Also there is explain of my query:
explain select * from users where yandex_id = 65250508;
+------+-------------+-------+------+---------------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------------------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | users | ALL | UNIQ_1483A5E988FDD79D,yandex_id | NULL | NULL | NULL | 1820017 | Using where |
+------+-------------+-------+------+---------------------------------+------+---------+------+---------+-------------+
and describe of table:
describe users;
+-------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| ts | int(10) unsigned | NO | MUL | NULL | |
| last_ts | int(10) unsigned | NO | MUL | NULL | |
| last_mail | int(10) unsigned | NO | | NULL | |
| photo | varchar(32) | YES | | NULL | |
| name | varchar(48) | YES | | NULL | |
| email | varchar(48) | YES | UNI | NULL | |
| state | smallint(6) | NO | MUL | NULL | |
| ip | bigint(20) unsigned | NO | | NULL | |
| gender | varchar(1) | NO | | NULL | |
| facebook_id | varchar(64) | YES | UNI | NULL | |
| mailru_id | varchar(64) | YES | UNI | NULL | |
| vk_id | varchar(64) | YES | UNI | NULL | |
| yandex_id | varchar(64) | YES | UNI | NULL | |
| google_id | varchar(64) | YES | UNI | NULL | |
| roles | longtext | YES | | NULL | |
| is_active | tinyint(1) | NO | MUL | 1 | |
+-------------+---------------------+------+-----+---------+----------------+
17 rows in set (0.00 sec)
Try USE INDEX(update_index) in your query explicitly.
Sometimes the optimizer makes wrong choice in selecting the index because of which the query is becoming slow.
I have resolved my issue. So, problem was in that i'm using in where integer value, but my field vas defined as varchar, so when i have changed searching id to string, it starts working perfect
MariaDB [hrabr]> select * from users force index(yandex_id) where yandex_id = 65250508;
1 row in set (13.81 sec)
and with string:
MariaDB [hrabr]> select * from users force index(yandex_id) where yandex_id = '65250508';
1 row in set (0.00 sec)
I hope it will help someone!

Complicated join and MAX() query in MySQL

I need to make a join across 4 tables whilst picking the maximum (i.e. most recent) timestamp of test to associate with a person. For each student in a class, I want to lookup what their most recent test is, and get its ID and timestamp
SELECT students.ref,
students.fname,
students.sname,
classes.name AS 'group',
tests.id,
max(tests.timestamp)
FROM tests, students, classlinks, classes
WHERE tests.ref=students.ref AND
classlinks.ref=students.ref AND
classlinks.classid=29 AND
tests.grade=2 AND
tests.subject=2
GROUP BY students.ref
ORDER BY students.sname ASC, students.fname ASC
looks like it is perfect: for each student in a class, it gives the timestamp of their most recent test. Unfortunately, the test ID associated with that timestamp is wrong: it is just giving the test ID of a random test.
If I change the 'group by' to be
GROUP BY students.ref, tests.id
then the query matches correct test IDs to correct timestamps, but now there are several entries for each student. Does anyone have any advice so that I can get one row for each student, with correct test ID matched to correct most recent timestamp? Any help appreciated. Thanks.
Table descriptions:
mysql> describe students;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ref | varchar(50) | NO | UNI | NULL | |
| fname | varchar(22) | NO | | NULL | |
| sname | varchar(22) | NO | | NULL | |
| school | int(11) | NO | | NULL | |
| year | int(11) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> describe classes;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| subject | int(11) | YES | MUL | NULL | |
| type | int(11) | YES | | 1 | |
| school | int(11) | YES | | NULL | |
| year | int(11) | YES | | NULL | |
| name | varchar(50) | YES | | NULL | |
+---------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> describe classlinks;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ref | varchar(50) | YES | MUL | NULL | |
| subject | int(11) | YES | | NULL | |
| school | int(11) | YES | | NULL | |
| classid | int(11) | YES | MUL | NULL | |
| type | int(11) | YES | | 1 | |
+---------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> describe tests;
+------------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| subject | int(11) | YES | | NULL | |
| ref | varchar(22) | NO | MUL | NULL | |
| test | int(3) | NO | | NULL | |
| grade | varchar(22) | NO | | NULL | |
| timestamp | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| lastupdate | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
I am assuming that the combination of (ref,timestamp) is unique in tests table. Here is my solution but I don't have any of your sample data to verify it. If it is incorrect than post a sample data so that I can test it.
UPDATE
Here is the update query which is working check the sqlfiddle
SELECT students.ref,
students.fname,
students.sname,
classes.name AS 'group',
tests.id,
T.timestamp
FROM (select ref,max(timestamp) as timestamp from tests group by ref)as T
natural join tests, students, classlinks, classes
WHERE
T.ref=students.ref AND
classlinks.ref=students.ref AND
classlinks.classid=classes.id AND
classlinks.classid=29 AND
tests.grade=2 AND
tests.subject=2
ORDER BY students.sname ASC, students.fname ASC
Using the logic in SQL the query can be written as follows, not sure about mySQL but hope the logic works.
Select ref
,fname
,sname
,ID
,group
,Timestamp
From
(select
S.ref
,S.fname
,S.sname,
,T.id
,classes.name AS 'group'
,T.timestamp
from
tests T,students S, classlinks, classes
Where
T.ref=S.ref and
T.grade=2 AND
classlinks.ref=students.ref AND
classlinks.classid=29 AND
classlinks.classid=classes.id AND
T.subject=2 ) A
inner join
(SELECT tests.ref
,max(tests.timestamp)
FROM
tests
group by
tests.ref
) B
on
A.ref=b.ref and
A.timestamp = b.timestamp

mySQL adding column breaks data

I have succesfully created a database in mySQL using the commandline and imported some data. It currently looks like this..
desc data;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| code | varchar(10) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
SELECT * FROM data;
+----+----------+
| id | code |
+----+----------+
| 1 | 123abc
| 2 | 234def
| 3 | 567ghi
| 4 | 890jkl
I would like to add a column to the table called timestamp, I am doing this with..
alter table data add timestamp VARCHAR(20);
But then my table looks like this...
desc data;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| code | varchar(10) | YES | | NULL | |
| timestamp | varchar(20) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
SELECT * FROM data;
+----+----------+-----------+
| id | code | timestamp |
+----+----------+-----------+
| NULL |
| NULL |
| NULL |
| NULL |
Where am I going wrong?
here you can see the backticks
alter table `data` add `timestamp` VARCHAR(20);
SAMPLE
MariaDB []> desc data;
+-------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| e | enum('x1','x2','x3') | YES | | NULL | |
+-------+----------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
MariaDB []> alter table `data` add `timestamp` VARCHAR(20);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB []> desc data;
+-----------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| e | enum('x1','x2','x3') | YES | | NULL | |
| timestamp | varchar(20) | YES | | NULL | |
+-----------+----------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
Table Data
MariaDB [who]> select * from `data`;
+----+------+-----------+
| id | e | timestamp |
+----+------+-----------+
| 1 | x1 | NULL |
| 2 | x2 | NULL |
+----+------+-----------+
2 rows in set (0.00 sec)
MariaDB [who]>

Find all rows from table1 that have zero rows in table2 linked to it by foreign key [duplicate]

This question already has answers here:
Return row only if value doesn't exist
(2 answers)
Closed 7 years ago.
The foreign key trade.ticker_id point to ticker.id.
I want to find all rows in 'ticker' that have zero rows in 'trades' linked to it.
mysql> describe trade;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| time | datetime | NO | | NULL | |
| price | float | NO | | NULL | |
| quantity | int(11) | NO | | NULL | |
| source | varchar(64) | YES | | NULL | |
| buyer | varchar(64) | YES | | NULL | |
| seller | varchar(64) | YES | | NULL | |
| initiator | varchar(64) | YES | | NULL | |
| ticker_id | int(11) | YES | MUL | NULL | |
+-----------+-------------+------+-----+---------+----------------+
9 rows in set (0,00 sec)
mysql> describe ticker;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | NO | | NULL | |
| long_name | varchar(250) | YES | | NULL | |
| exchange_id | int(11) | YES | MUL | NULL | |
+-------------+--------------+------+-----+---------+----------------+
4 rows in set (0,00 sec)
Try this:
SELECT * FROM ticker WHERE id NOT IN (SELECT ticker_id FROM trade)
You can use left join and is null or in other words anti join
select tc.* from ticker tc
left join trade tr on tr.ticker_id = tc.id
where tr.ticker_id is null

Mysql trigger script not working

I've been trying to set up a trigger in mysql to no avail.
Here are the tables related to it:
mysql> describe ttloki;
+-------------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-----------+------+-----+-------------------+-----------------------------+
| Lokinumero | int(11) | NO | PRI | NULL | auto_increment |
| Ttnumero | int(11) | NO | MUL | NULL | |
| Kirjausaika | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+-----------+------+-----+-------------------+-----------------------------+
3 rows in set (0.00 sec)
mysql> describe tyontekija;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| Numero | int(11) | NO | PRI | NULL | |
| Sukunimi | varchar(40) | NO | | NULL | |
| Etunimi | varchar(40) | NO | | NULL | |
| Osasto | int(11) | YES | MUL | NULL | |
| Lahios | varchar(40) | YES | | NULL | |
| Postino | varchar(5) | NO | MUL | NULL | |
| Puhelin | varchar(16) | YES | | NULL | |
| Palkka | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
My last tryout trigger is this:
create trigger uusitt
after insert on TYONTEKIJA
for each row
insert into TTLOKI(Ttnumero) values
(old.TYONTEKIJA.Numero);
Whenever I try to insert into TYONTEKIJA it gives me errors about whatever is in values in the trigger.
mysql> insert into TYONTEKIJA(Numero,Sukunimi,Etunimi,Osasto,Lahios,Postino,Puhelin,Palkka) values
-> (220000, "Saarikoski", "Pekka", 5, "Umpikuja 1", "02760", "060-7358461", 3000);
ERROR 1054 (42S22): Unknown column 'old.TYONTEKIJA.Numero' in 'field list'
I don't understand how to set up this kind of a trigger correctly.
What should I change to fix this?
When you insert a value, you cannot use old identifier because there is no old values yet. Maybe you mean, new.Numero?