I had a query like
SELECT name, town FROM clients WHERE course = 1;
and it gave me some results.
But i noticed the query didn't output the latest entries. I look into the table clients with phpmyadmin and i saw more course fields with value 1.
After i changed the query to
SELECT name, town FROM clients WHERE course = '1';
i got the right output.
My question: why is this? and why did i get some results with the first query ?
ps: course is an enum field ( '0','1').
1 is either an integer value, or 'TRUE', or ... (ambiguous) while '1' is a string value.
As explained in the MySQL-documentation for the ENUM-type:
An ENUM is a string object with a value chosen from a list of
permitted values that are enumerated explicitly in the column
specification at table creation time.
[...]
If you wish to use a number as an enumeration value, you must enclose
it in quotation marks. If the quotation marks are omitted, the number
is regarded as an index. For this and other reasons—as explained later
in this section—we strongly recommend that you do not use numbers as
enumeration values.
So, ENUM is a string object, therefore you need to reference to it as a string.
Related
Need some help with the MySQL query.
I have a table named custom_fields with attributes id, user_id, name, value etc.
name and values are of type string and it can store sometimes JSON also in the form of a string.
Requirement:
I need to list out all the unique user_id which satisfies below conditions
1) name must be starting with street_address_
2) value is a hash but stored as a string. if the country code is in ('us', 'in')
Here is the sample record.
id: 90489,
user_id: 30207,
name: "street_address_billing",
value:"{\"street_address1\":\"401 Lenora Street\",\"street_address2\":\"\",\"city\":\"Belltown\",\"locality\":\"Seattlel\",\"province\":\"WA\",\"postal_code\":\"111\",\"country_code\":\"us\"}",
deleted_at: nil,
active: true
Here is the query I'm trying. But it is not working. I have no error but it does not give any results either. instead of in if i use = and single value sometimes it gives the value.
SELECT id,user_id, #addr:= replace(replace(replace(replace(value, ':“', ':"'), '”,', '",'), '”}', '"}'), '{“' , '{"'), JSON_EXTRACT(#addr, '$.country_code') as billing_country
FROM `custom_fields` WHERE `custom_fields`.`active` = TRUE AND (name REGEXP '^street_address_')
AND JSON_EXTRACT(#addr, '$.country_code') in ('us', 'in');s
Despite the fact that SELECT syntax puts the select-list above the WHERE clause, WHERE conditions are evaluated first, to restrict the rows returned by the query. Then for those rows only, expressions in the select-list are evaluated. So your variables defined in the select-list cannot be used in the WHERE clause.
So you need to reference the column itself in your WHERE conditions:
SELECT id,user_id, JSON_UNQUOTE(JSON_EXTRACT(value, '$.country_code')) AS billing_country
FROM `custom_fields` WHERE `custom_fields`.`active` = TRUE AND (name REGEXP '^street_address_')
AND JSON_UNQUOTE(JSON_EXTRACT(value, '$.country_code')) IN ('us', 'in');
Also you need to use JSON_UNQUOTE() because the return value of JSON_EXTRACT() is not a plain string — it's a JSON document that happens to be a scalar. So it will return "us".
I've removed all the replace() stuff because you shouldn't need it. If you use JSON data, you should store it in a JSON column, and that will reject invalid JSON that contains smart-quote characters.
Why if I run a query with gibberish at the end of the where condition it incorrectly returns a result.
Example:
SELECT * FROM contractor_table WHERE contractorID = '97sd'
I am getting the row with the ID 97, when I should get no result.
What is happening here is that you are comparing the contractorID column, which is integer or some other numeric type, against a string literal 97sd. This doesn't make any sense, so MySQL, based on its casting rules, attempts to first cast 97sd to an integer. Consider the result of the following query:
SELECT CAST('97sd' AS unsigned);
In fact, this outputs just 97, the integer. So, in practice this means that the "gibberish" at the end of your string literal, which begins with an integer, will be ignored by MySQL.
But best practice here is to always compare columns against the correct literal types. So use the following version always, for best results:
SELECT * FROM contractor_table WHERE contractorID = 97;
This happends when you have column type int or other numeric if you convert it into varchar than it will retun no output
i'm working with mysql in a nodejs web app. I don't understand why when I ask for some id (key) it gives me more than 1 result.
When I:
SELECT * FROM products WHERE id = 1;
This happens, I get 3 results, but I only want 1:
1, 001 and 0000001.
I just want the info of one product (id: 1 in this example)
How can I fix this?
ID type is varchar(20)
If I use LIKE instead of = my result changes:
SELECT * FROM products WHERE id LIKE 0000001;
I get the info of id = 1 instead 0000001. Don't know why.
Thanks
The WHERE clause of your query contains a comparison of a literal numeric value with a string (column id).
When it needs to compare values of different type, MySQL uses several rules to convert one or both of the values to a common type.
Some of the type conversion rules are not intuitive. The last rule is the only one that matches a comparison of an integer number with a string:
In all other cases, the arguments are compared as floating-point (real) numbers.
When they are converted to floating-point (real) numbers, 1 (integer), '1', '0001' and '0000001' are all equal.
In order to get an exact match the literal value you put in the query must have the same type as the column id (i.e string). The query should be:
SELECT * FROM products WHERE id = '1'
The problem is that you are looking by a varchar type using an integer cast.
Try to add quotes to the id parameter:
SELECT * FROM products WHERE id = '1';
If you want to add integer ids with with leading zeros, I recommend you to use the zerofill option:
https://dev.mysql.com/doc/refman/5.5/en/numeric-type-attributes.html
If you want to use use alphanumeric values then keeps the ID type as varchar, but remember to enclose the search param into quotes.
Numbers in MySQL (and the real world) don't have leading zeros. Strings do.
So, you just need to make the comparison using the right type:
SELECT *
FROM products
WHERE id = '1';
What happens with your original query is that the id is converted to a number. And '1', '001' and '0000001' are all converted to the same integer -- 1. Hence, all three pass the filter.
In a MySQL table i have a field, containing this value for a given record : "1908,2315,2316"
Here is my sql Query :
SELECT * FROM mytable WHERE 2316 IN (myfield)
I got 0 results!
I tried this :
SELECT * FROM mytable WHERE 2315 IN (myfield)
Still 0 results
And then i tried this :
SELECT * FROM mytable WHERE 1908 IN (myfield)
Surprisingly i obtained the record when searching with 1908! What should i do to also obtain the record when searching with 2315 and 2316 ? What am i missing ?
Thanks
You appear to be storing comma delimited values in a field. This is bad, bad, bad. You should be using a junction table, with one row per value.
But, sometimes you are stuck with data in a particular structure. If so, MySQL provides the find_in_set() functions.
SELECT *
FROM mytable
WHERE find_in_set(2316, myfield) > 0;
You can't use IN() over comma separated list of no.s its better to normalize your structure first for now you can use find_in_set to find results matching with comma separated string
SELECT * FROM mytable WHERE find_in_set('1908',myfield) > 0
This question has been asked and answered before, but I don't want to hunt for it; this question should be closed as a duplicate. But, to answer your question:
The commas in the string, the column value, are just characters. Those are part of the string. They aren't seen as "separators" between values in the SQL text. The way SQL sees it, the column contains a single value, not a "list" of values.
So, in your query, the IN (field) is equivalent to an equals comparison. It's equivalent to comparing to a string. For example:
... WHERE 2316 = '1908,2315,2316'
And those aren't equal, so the row isn't returned. The "surprisingly" finding of a match, in the case of:
... WHERE 1908 IN ('1908,2315,2316')
that's explained because that string is being evaluated in a numeric context. That is, the comparison returns true, because all of these also true:
... WHERE 1908 = '1908,2315,2316' + 0
... WHERE 1908 = '1908xyz' + 0
... WHERE 1908 = '1907qrs' + 1
(When evaluated in a numeric context, a string gets converted to numeric. It just happens that the string evaluates to a numeric value that equals the integer value it's being comparing to.)
You may be able to make use of the MySQL FIND_IN_SET function. For example:
... WHERE FIND_IN_SET(2316,'1908,2315,2316')
But, please seriously reconsider the design of storing comma separated list. I recommend Bill Karwin's "SQL Antipatterns" book...
http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557
In mysql IN clause is utilized as
SELECT * FROM mytable WHERE column_name IN (set_of_values) ;
Mention column name instead of values
Please try
SELECT * FROM mytable WHERE LOCATE(CONCAT (',', 2316 ','), CONCAT (',',myfield,',' ) ) <>0
This case is similar to: S.O Question; mySQL returns all rows when field=0, and the Accepted answer was a very simple trick, to souround the ZERO with single quotes
FROM:
SELECT * FROM table WHERE email=0
TO:
SELECT * FROM table WHERE email='0'
However, my case is slightly different in that my Query is something like:
SELECT * FROM table WHERE email=(
SELECT my_column_value FROM myTable WHERE my_column_value=0 AND user_id =15 LIMIT 1 )
Which in a sense, becomes like simply saying: SELECT * FROM table WHERE email=0, but now with a Second Query.
PLEASE NOTE: It is a MUST that I use the SECOND QUERY.
When I tried: SELECT * FROM table WHERE email='( SELECT my_column_value FROM myTable WHERE my_column_value=0 LIMIT 1 )' (Notice the Single Quotes on the second query)
MySql SCREAMED Errors near '(.
How can this be achieved
Any Suggestion is highly honored
EDIT1: For a visual perspective of the Query
See the STEN_TB here: http://snag.gy/Rq8dq.jpg
Now, the main aim is to get the sten_h where rawscore_h = 0;
The CURRENT QUERY as a whole.
SELECT sten_h
FROM sten_tb
WHERE rawscore_h = (
SELECT `for_print_stens_rowscore`
FROM `for_print_stens_tb`
WHERE `for_print_stens_student_id` =3
AND `for_print_stens_factor_name` = 'Factor H' )
The result of the Second Query can be any number including ZERO.
Any number from >=1 Works and returns a single corresponding value from sten_h. Only =0 does not Work, it returns all rows
That's the issue.
CORRECT ANSWER OR SOLUTION FOR THIS
Just in case someone ends up in this paradox, the Accepted answer has it all.
SEE STEN_TB: http://snag.gy/Rq8dq.jpg
SEE The desired Query result here: http://snag.gy/wa4yA.jpg
I believe your issue is with implicit datatype conversions. You can make those datatype conversions explicit, to gain control.
(The "trick" with wrapping a literal 0 in single quotes, that makes the literal a string literal, rather than a numeric.)
In the more general case, you can use a CAST or CONVERT function to explicitly specify a datatype conversion. You can use an expression in place of a column name, wherever you need to...
For example, to get the value returned by my_column_value to match the datatype of the email column, assuming email is character type, something like:
... email = (SELECT CONVERT(my_column_value,CHAR(255)) FROM myTable WHERE ...
or, to get the a literal integer value to be a string value:
... FROM myTable WHERE my_column_value = CONVERT(0,CHAR(30)) ...
If email and my_column_value are just indicating true or false then they should almost certainly be both BIT NOT NULL or other two-value type that your schema uses for booleans. (Your ORM may use a particular one.) Casting is frequently a hack made necessary by a poor design.
If it should be a particular user then you shouldn't use LIMIT because tables are unordered and that doesn't return a particular user. Explain in your question what your query is supposed to return including exactly what you mean by "15th".
(Having all those similar columns is bad design: rawscore_a, sten_a, rawscore_b, sten_b,... . Use a table with two columns: rawscore, sten.)