why is MySQL casting varchar as integer when WHERE clause is present? - mysql

I have a MySQL database table, student_import_record, with a student_id varchar(50) field that can contain alphanumeric data.
When I run this SELECT statement:
select student_id from student_import_record;
I get the VARCHAR results as expected:
0001546
0001660
0002207
0002349
But when I run this SELECT statement with a WHERE clause:
select student_id from student_import_record where student_import_id = 185;
I get results that appear to be cast as an integer:
1546
1660
2207
2349
How do I prevent this casting when using a WHERE clause?
Full Table schema:
mysql> describe student_import_record;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| student_id | varchar(50) | NO | | NULL | |
| relationship | varchar(50) | NO | | NULL | |
| date_of_birth | varchar(50) | NO | | NULL | |
| first_name | varchar(255) | NO | | NULL | |
| last_name | varchar(255) | NO | | NULL | |
| gender | varchar(10) | NO | | NULL | |
| student_type | varchar(50) | YES | | NULL | |
| email | varchar(255) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
| address | varchar(255) | YES | | NULL | |
| address2 | varchar(255) | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| state | varchar(50) | YES | | NULL | |
| zip | varchar(50) | YES | | NULL | |
| mandate | varchar(10) | YES | | NULL | |
| ssn | varchar(11) | YES | | NULL | |
| suffix | varchar(20) | YES | | NULL | |
| department | varchar(50) | YES | | NULL | |
| password | varchar(255) | YES | | NULL | |
| benefit1 | varchar(255) | YES | | NULL | |
| benefit2 | varchar(255) | YES | | NULL | |
| benefit3 | varchar(255) | YES | | NULL | |
| benefit4 | varchar(255) | YES | | NULL | |
| benefit5 | varchar(255) | YES | | NULL | |
| benefit6 | varchar(255) | YES | | NULL | |
| plan1 | varchar(255) | YES | | NULL | |
| plan2 | varchar(255) | YES | | NULL | |
| plan3 | varchar(255) | YES | | NULL | |
| plan4 | varchar(255) | YES | | NULL | |
| plan5 | varchar(255) | YES | | NULL | |
| plan6 | varchar(255) | YES | | NULL | |
| account | int(11) | NO | | NULL | |
| enrollment_config | int(11) | NO | | NULL | |
| imported_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| status | smallint(6) | YES | | NULL | |
| status_description | longblob | YES | | NULL | |
| student_import_id | int(11) | NO | | NULL | |
Result sets
mysql> select student_id from student_import_record where student_import_id = 185 limit 10;
+------------+
| student_id |
+------------+
| 1546 |
| 1660 |
| 2207 |
| 2349 |
| 3123 |
| 3208 |
| 3319 |
| 3811 |
| 3837 |
| 3842 |
+------------+
10 rows in set (0.02 sec)
mysql> select student_id from student_import_record limit 10;
+------------+
| student_id |
+------------+
| 0001546 |
| 0001660 |
| 0002207 |
| 0002349 |
| 0003123 |
| 0003208 |
| 0003319 |
| 0003811 |
| 0003837 |
| 0003842 |
+------------+
10 rows in set (0.00 sec)

Looks like you have already figured out what was going on. In the hope to close out this question, here's a link that explains type conversion in expression evaluation: https://dev.mysql.com/doc/refman/5.5/en/type-conversion.html
When an operator is used with operands of different types, type
conversion occurs to make the operands compatible. Some conversions
occur implicitly. For example, MySQL automatically converts numbers to
strings as necessary, and vice versa.
mysql> SELECT 1+'1';
-> 2
In your case, MySQL might be seeing arithmetic operation in the WHERE clause and performing implicit conversion to integers in that column. My recommendation is to structure the table, if possible, in a manner that numbers are in numeric column and non-numeric data is in its appropriate column. When there's mixed content, you could force the data to be character.

Related

FULLTEXT mysql return empty

I have a table with the following structure:
+-----------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+-------------------+-----------------------------+
| imovel_id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| img_dest | varchar(111) | YES | | NULL | |
| data_imob | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| finalidade_imob | varchar(51) | NO | MUL | NULL | |
| status_imob | varchar(51) | NO | | NULL | |
| tipo_imob | varchar(255) | YES | | NULL | |
| uf_imob | varchar(51) | NO | MUL | NULL | |
| cidade_imob | varchar(255) | NO | | NULL | |
| bairro_imob | varchar(255) | YES | | NULL | |
| rua_imob | varchar(255) | YES | | NULL | |
| vaga_imob | varchar(255) | YES | | NULL | |
| dorms_imob | char(2) | YES | | NULL | |
| tamanho_imob | varchar(222) | YES | | NULL | |
| valor_imob | varchar(255) | YES | | 0 | |
| titulo_imob | varchar(255) | YES | | NULL | |
| descricao_imob | longtext | YES | | NULL | |
| carac_imob | varchar(255) | YES | | NULL | |
+-----------------+--------------+------+-----+-------------------+-----------------------------+
If I run this query:
SELECT * FROM form_imovel LEFT JOIN (form_user) ON (form_user.user_id = form_imovel.user_id) WHERE MATCH(finalidade_imob,status_imob,tipo_imob,uf_imob,cidade_imob,bairro_imob,dorms_imob,valor_imob) AGAINST ('Comprar' IN BOOLEAN MODE);
Where Comprar is the value from finalidade_imob column, I have the right results, that work with all columns, except uf_imobcolumn.
The uf_imobcolumns have values like: SP,MG,RJ.
If I try run the following query, it returns empty:
SELECT * FROM form_imovel LEFT JOIN (form_user) ON (form_user.user_id = form_imovel.user_id) WHERE MATCH(finalidade_imob,status_imob,tipo_imob,uf_imob,cidade_imob,bairro_imob,dorms_imob,valor_imob) AGAINST ('SP' IN BOOLEAN MODE);
Even though that column has so many SP registers.
Fiddle example

Why LEFT JOIN give me always the primery id value in MySQL for Python?

I have the next GUI made in Python which lets me to load all the data saved in a MySQL table for tenants, and just one data from a related table called 'contracts' (marked with a red circle).
enter image description here
The Python code I use for loading this form is the next one:
def fill_entries():
i = lb.curselection()[0]
valor = lb.get(i)
nombs, apells = _arrendatarios[valor]
cursor.execute("SELECT *, c_cod FROM arrendatarios LEFT JOIN contratos ON arrendatarios.a_cc = contratos.a_cc WHERE a_nombres = %s AND a_apellidos = %s", (nombs, apells))
result = cursor.fetchall()
connect.commit()
for item in result:
d1 = item[1] #ID
d2 = item[2] #Mr/Mrs
d3 = item[3] #City
d4 = item[4] #Names
d5 = item[5] #Last names
#------------And so on
d53 = item[53] # Num Contract
cedula.set(d1)
titulo.set(d2)
residencia.set(d3)
nombres.set(d4)
apellidos.set(d5)
direccion.set(d6)
#------------And so on
numcontract.set(d53)# Num Contract
But the thing is that what I want from the contracts table is the c_cod data, not de c_id, because part of this table description is this:
MariaDB> desc contratos;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| c_id | int(11) | NO | UNI | NULL | auto_increment |
| c_cod | int(11) | NO | PRI | NULL | |
| a_cc | varchar(50) | YES | MUL | NULL | |
| inquilino | varchar(100) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
And if, for example, I run the query in MySQL I got this:
MariaDB> SELECT arrendatarios.a_cc, c_cod FROM arrendatarios LEFT JOIN contratos ON arrendatarios.a_cc = contratos.a_cc;
+------------+-------+
| a_cc | c_cod |
+------------+-------+
| 900157048 | NULL |
| 71337237 | NULL |
| 43057196 | 22789 |
| 542550033 | NULL |
| 3502278 | NULL |
| 3472265 | NULL |
| 32460023 | NULL |
| And so on... |
+------------+-------+
34 rows in set (0.01 sec)
But Python is not drawing me the c_cod from contracts table but the c_id as if I were running:
MariaDB> SELECT arrendatarios.a_cc, c_id FROM arrendatarios LEFT JOIN contratos ON arrendatarios.a_cc = contratos.a_cc;
+------------+------+
| a_cc | c_id |
+------------+------+
| 900157048 | NULL |
| 71337237 | NULL |
| 43057196 | 8 |
| 542550033 | NULL |
| 3502278 | NULL |
| 3472265 | NULL |
| 32460023 | NULL |
| And so on... |
+------------+------+
34 rows in set (0.00 sec)
No matter what column I write, it always draws me the same result, the c_id. I'm a newbie with MySQL, I just new the basic. So, am I using wrong LEFT JOIN? Because what I want is just to show tenant info and this contract number n matter if it has it or not.
Here's the description of the tenants table too.
MariaDB> desc arrendatarios;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| a_id | int(11) | NO | UNI | NULL | auto_increment |
| a_cc | varchar(50) | NO | PRI | NULL | |
| a_titulo | varchar(20) | YES | | NULL | |
| a_reside | varchar(50) | YES | | NULL | |
| a_nombres | varchar(50) | YES | | NULL | |
| a_apellidos | varchar(50) | YES | | NULL | |
| a_direccion | varchar(50) | YES | | NULL | |
| a_telefono | varchar(50) | YES | | NULL | |
| a_envio | varchar(50) | YES | | NULL | |
| a_email | varchar(50) | YES | | NULL | |
| a_celular | varchar(50) | YES | | NULL | |
| a_dia | int(11) | YES | | NULL | |
| a_mes | varchar(10) | YES | | NULL | |
| a_cumple | date | YES | | NULL | |
| a_profesion | varchar(50) | YES | | NULL | |
| a_empresa | varchar(50) | YES | | NULL | |
| a_oficina | varchar(50) | YES | | NULL | |
| a_tel | varchar(50) | YES | | NULL | |
| a_fax | varchar(50) | YES | | NULL | |
| a_banco | varchar(50) | YES | | NULL | |
| a_tcuenta | varchar(10) | YES | | NULL | |
| a_numcuenta | varchar(50) | YES | | NULL | |
| a_tpersona | int(11) | YES | | NULL | |
| a_retefuente | int(11) | YES | | NULL | |
| a_reteiva | int(11) | YES | | NULL | |
| a_contribuyente | int(11) | YES | | NULL | |
| a_gfactura | int(11) | YES | | NULL | |
| a_gcheque | int(11) | YES | | NULL | |
| a_nota | varchar(200) | YES | | NULL | |
| co1_cc | varchar(50) | YES | | NULL | |
| co1_nombres | varchar(50) | YES | | NULL | |
| co1_dir | varchar(50) | YES | | NULL | |
| co1_tel1 | varchar(50) | YES | | NULL | |
| co1_cargo | varchar(50) | YES | | NULL | |
| co1_empresa | varchar(59) | YES | | NULL | |
| co1_oficina | varchar(50) | YES | | NULL | |
| co1_tel2 | varchar(50) | YES | | NULL | |
| co2_cc | varchar(50) | YES | | NULL | |
| co2_nombres | varchar(50) | YES | | NULL | |
| co2_dir | varchar(50) | YES | | NULL | |
| co2_tel1 | varchar(50) | YES | | NULL | |
| co2_cargo | varchar(50) | YES | | NULL | |
| co2_empresa | varchar(59) | YES | | NULL | |
| co2_oficina | varchar(50) | YES | | NULL | |
| co2_tel2 | varchar(50) | YES | | NULL | |
| co3_cc | varchar(50) | YES | | NULL | |
| co3_nombres | varchar(50) | YES | | NULL | |
| co3_dir | varchar(50) | YES | | NULL | |
| co3_tel1 | varchar(50) | YES | | NULL | |
| co3_cargo | varchar(50) | YES | | NULL | |
| co3_empresa | varchar(59) | YES | | NULL | |
| co3_oficina | varchar(50) | YES | | NULL | |
| co3_tel2 | varchar(50) | YES | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
53 rows in set (0.06 sec)
As commented this solved the problem:
cursor.execute("SELECT arrendatarios.*, c_cod FROM arrendatarios LEFT JOIN contratos ON arrendatarios.a_cc = contratos.a_cc WHERE a_nombres = %s AND a_apellidos = %s", (nombs, apells))

MySQL command run on terminal is stuck, but phpmyadmin success

I want to get location from members IP. I can use the command on phpmyadmin, and it costs about 2 seconds. But it will be stuck when the command is executed on MySQL through terminal. How can I fix the problem.
SQL Command:
SELECT
ID,country
FROM
(SELECT ID,substring_index(members.server_ids,',',1) AS IP FROM members) AS A
JOIN
(SELECT country,start,end FROM ip) AS B
ON
INET_ATON(A.IP) BETWEEN INET_ATON(B.start) AND INET_ATON(B.end);
desc members:
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| USER_NAME | varchar(100) | NO | UNI | NULL | |
| PASSWORD | varchar(32) | YES | | NULL | |
| NAME | varchar(100) | YES | | NULL | |
| EMAIL | varchar(50) | YES | MUL | NULL | |
| SAFE_EMAIL | varchar(50) | YES | | NULL | |
| NICK_NAME | varchar(100) | YES | MUL | NULL | |
| GENDER | tinyint(1) | YES | | 0 | |
| BIRTHDAY | date | YES | | NULL | |
| CREATEDAY | datetime | YES | | NULL | |
| PHONE | varchar(20) | YES | | NULL | |
| MOBILE | varchar(15) | YES | | NULL | |
| ID_CARD | varchar(32) | YES | | NULL | |
| COUNTY | int(11) | YES | | NULL | |
| ADDRESS | varchar(255) | YES | | NULL | |
| LOGIN_TIME | datetime | YES | | NULL | |
| BUY_SN | varchar(50) | YES | | NULL | |
| BUY_KIND | varchar(50) | YES | | NULL | |
| PARTNER_SN | varchar(50) | YES | | NULL | |
| cookie_value | varchar(100) | YES | | NULL | |
| CONSIGNEE_INFO | int(11) | YES | MUL | NULL | |
| LOGIN_COUNT | int(11) | YES | | NULL | |
| PAY_COUNT | int(11) | YES | | NULL | |
| status | tinyint(4) | YES | | 1 | |
| experience | int(11) | YES | | 0 | |
| amount | int(11) | YES | | 0 | |
| score | int(11) | YES | | 0 | |
| is_facebook_account | tinyint(4) | YES | | 0 | |
| avatar | varchar(200) | YES | | NULL | |
| avatar_status | tinyint(1) | YES | | 0 | |
| member_authhash | varchar(50) | YES | | NULL | |
| job | varchar(50) | YES | | NULL | |
| server_ids | varchar(255) | YES | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
SELECT ID,server_ids FROM members LIMIT 10000,1;
+-------+--------------------------+
| ID | server_ids |
+-------+--------------------------+
| 20005 | 61.20.167.219, 127.0.0.1 |
+-------+--------------------------+
desc ip:
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| country | char(2) | NO | | NULL | |
| type | char(4) | NO | | NULL | |
| start | varchar(15) | NO | MUL | NULL | |
| end | varchar(15) | NO | MUL | NULL | |
+---------+------------------+------+-----+---------+----------------+
SELECT * FROM ip LIMIT 100,1;
+-----+---------+------+-----------+---------------+
| id | country | type | start | end |
+-----+---------+------+-----------+---------------+
| 101 | IN | ipv4 | 1.187.0.0 | 1.187.255.255 |
+-----+---------+------+-----------+---------------+
phpMyAdmin automatically adds a LIMIT clause to the query. Because you do not have an ODER BY clause, MySQL sends the results as soon as it has found the number of records that you requested in the LIMIT clause.
Add a LIMIT clause to the query that you execute on the command line.

Include null values in SQL query

I have the following four tables in my database:
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| complex_id | int(11) | NO | PRI | NULL | auto_increment |
| complex_name | varchar(45) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| machine_id | int(11) | NO | PRI | NULL | auto_increment |
| complex_id | int(11) | NO | MUL | NULL | |
| machine_name | varchar(45) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| devices_id | int(11) | NO | PRI | NULL | auto_increment |
| machine_id | int(11) | NO | MUL | NULL | |
| description | varchar(255) | NO | | NULL | |
| location | varchar(255) | YES | | NULL | |
| verification | varchar(255) | YES | | NULL | |
| rack_num | varchar(8) | YES | | NULL | |
| section_num | varchar(8) | YES | | NULL | |
| color_or_number | varchar(16) | YES | | NULL | |
| normal_position | varchar(16) | YES | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| pnp_id | int(11) | NO | PRI | NULL | auto_increment |
| devices_id | int(11) | NO | MUL | NULL | |
| pnp_num | varchar(45) | NO | | NULL | |
+------------+-------------+------+-----+---------+----------------+
I am trying to get results formatted as follows (NULL values appear as blanks):
+------------+-------------+-----------------------+
| devices_id | description | pnpnum |
+------------+-------------+-----------------------+
| 1 | ex | 1234 |
| 2 | ex2 | 2345 |
| 3 | ex3 | |
| 4 | ex4 | 3456, 4567, 5678, 6879|
+------------+-------------+-----------------------+
Using the following SQL query,
SELECT *, GROUP_CONCAT(pnp.pnp_num separator ', ') pnpnum
FROM devices
JOIN pnp ON devices.devices_id = pnp.devices_id
WHERE devices.machine_id = 1
GROUP BY devices.devices_ID
ORDER BY devices.description;
my results are relatively close, however, I am unable to include a device if it has a null pnpnum.
+------------+-------------+-----------------------+
| devices_id | description | pnpnum |
+------------+-------------+-----------------------+
| 1 | ex | 1234 |
| 2 | ex2 | 2345 |
| 4 | ex4 | 3456, 4567, 5678, 6879|
+------------+-------------+-----------------------+
What is it that I am missing from my SQL statement that will allow me to include null values?
You need to use LEFT JOIN because even if there isn't a match, it will return all the results from the left table leaving the fields from the right table null.

Determine if a field from one table is like the field from another table and if so count occurrence and if less than 3 return the name

I have two tables images and Interactions in the same DB. I want to determine if the image.images which has a png file name for example
1001_A01_1-4_5mM_3AT_Xgal_7d_W.cropped.resized.grey.png is like plate_name.Interactions which would look like 1001_A01 and then count how many times the images show up. I should get 3 images if there are fewer than 3 images I would like to have plate_name.Interactions returned. I would like to do this using 1 query.
So far I have just tried to count how many occurrences there are but this is failing:
select plate_name.Interactions, count(*) as count from Interactions where plate_name.Interactions like image.images;
Here are the tables in question:
mysql> desc images;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| image | varchar(100) | NO | MUL | NULL | |
| user_id | varchar(50) | YES | | NULL | |
| project_id | varchar(50) | YES | | NULL | |
+------------+--------------+------+-----+---------+-------+
mysql> desc Interactions;
+----------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+-------------+------+-----+---------+-------+
| plate_name | varchar(25) | NO | MUL | NULL | |
| plate_number | int(11) | NO | MUL | NULL | |
| bait_sequence_name | varchar(25) | NO | | NULL | |
| bait_gene_promoter | varchar(25) | NO | MUL | NULL | |
| array_coord | varchar(25) | NO | | NULL | |
| transcriptor_factor | varchar(25) | NO | | NULL | |
| orf_name | varchar(25) | NO | | NULL | |
| y_coord | varchar(25) | NO | MUL | NULL | |
| x_coord | varchar(25) | NO | MUL | NULL | |
| orig_intensity_value | varchar(25) | NO | | NULL | |
| rc_intensity_value | varchar(25) | NO | | NULL | |
| ptp_intensity_value | varchar(25) | NO | | NULL | |
| z_score | varchar(25) | NO | MUL | NULL | |
| z_prime | varchar(20) | YES | | NULL | |
| call_type | varchar(25) | NO | | NULL | |
| bleed_over | varchar(25) | NO | MUL | NULL | |
| plate_median | int(11) | YES | MUL | NULL | |
| bait_gene | varchar(25) | NO | | NULL | |
| bait_prey_orf | varchar(25) | NO | | NULL | |
| human_call | varchar(25) | NO | | NULL | |
| modified_call | varchar(25) | NO | | NULL | |
| duplicate_call | varchar(25) | YES | | NULL | |
| user_id | varchar(25) | YES | MUL | NULL | |
| project_id | varchar(25) | YES | MUL | NULL | |
+----------------------+-------------+------+-----+---------+-------+
Added in response to Bobby's answer:
+----+-------------+--------------+-------+---------------+--------------+---------+--- ---+---------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+---------------+--------------+---------+--- ---+---------+-----------------------------------------------------------+
| 1 | SIMPLE | images | index | NULL | image | 208 | NULL | 19581 | Using where; Using index; Using temporary; Using filesort |
| 1 | SIMPLE | Interactions | range | plate_median | plate_median | 5 | NULL | 3714984 | Using where; Using join buffer |
+----+-------------+--------------+-------+---------------+--------------+---------+------+---------+-----------------------------------------------------------+
I think you write your table name and your column name in incorrect format..
if I'm right, the query should return only plate_name which it has less than 3 images,
so you can do it with a GROUP BY and HAVING method..
SELECT Iteractions.plate_name, count(*) as `count`
FROM Interactions, Images
WHERE Interactions.plate_name LIKE Images.image
GROUP BY Interactions.plate_name
HAVING count(*) < 3
Please try that, and tell me if that's not what you want.. :)