Using a number with mySQL IN() function - mysql

I am having trouble using mySQL IN() when using it with a number, rather than a field name.
My query is:
$query = "select rental_id from {$this->table_name}
where rental_id='$unit_id' AND '49' IN (specifications)";
The field specifications contains 20,10,49,22,18
An explanation states,
Note: #1003 /* select#1 */ select '270' AS `rental_id` from `mydatabase`.`rental_buildings` where 0
and shows and Extra of Impossible WHERE noticed after reading const tables
If I remove the single quotes from the 49, I get
Warning: #1292 Truncated incorrect DOUBLE value: '20,10,49,22,18'
Note: #1003
/* select#1 */ select '270' AS `rental_id`
from `mydatabase`.`rental_buildings`
where (('270' = '270') and (49 = '20,10,49,22,18'))
This seems like it should be very straightforward, but I can't get it to work. I'd appreciate any guidance

You can use FIND_IN_SET:
SELECT rental_id FROM ...
WHERE rental_id=? AND FIND_IN_SET(?, specifications)
Keep in mind this will be exceptionally slow and extremely punishing on datasets of non-trivial size as this must search through each field individually for all entries for that particular rental_id.
To fix this you need a proper relational table where your query would look like:
SELECT DISTINCT rental_id FROM specifications WHERE id=?
For that particular specification_id. This can be indexed and can be really fast.

Related

How to get the exact value from sql like query

I have a Mysql database that contains some category ids on it which stores comma-separated values on a table.
sql table view
By using select * from style where categories like '%8,%'; it returns all the values end with 8. For example, if the table rows have two values like 8 and 148 it returns both rows. But I want to get only the rows that contain 8. How to do it
Storing multiple values in a single column is a denormalised design that will almost always cause you problems. However you need to add commas to both sides and compare:
select *
from Style
where concat(',',Categories,',') like '%,8,%';
Like everyone else: normalize your data. But if you can't mySQL supports find_in_set() for set datatypes which this appears to be.
DEMO dbfiddle.uk
DOC LINK: Find_in_set()
DOC LINK: SET data type
SQL
With CTE as (SELECT 'T-Shrits' as baseCategory, '8,21,75,87,148' categories UNION ALL
SELECT 'T-Shrits' as baseCategory, '8,21,75,87,148' categories UNION ALL
SELECT 'T-Shrits - Long Sleeve' as baseCategory, '8,21,75,87,148,92' categories UNION ALL
SELECT 'T-Shrits' as baseCategory, '21,75,87,100,148' categories)
SELECT * FROM CTE where find_in_set(8,categories) >0
OR we can use a boolean evaluation and eliminate the > 0
SELECT * FROM CTE where find_in_set(8,categories)
Giving us:
+------------------------+-------------------+
| baseCategory | categories |
+------------------------+-------------------+
| T-Shrits | 8,21,75,87,148 |
| T-Shrits | 8,21,75,87,148 |
| T-Shrits - Long Sleeve | 8,21,75,87,148,92 |
+------------------------+-------------------+
Notes
Find_in_set() returns the Returns a value in the range of 1 to N in the pseudo array of the value being searched. We need to ensure the result is greater than 0 (or treat it as a Boolean) in order for the searched value to "exist" within a record column.
The engine didn't return my 4th union value in CTE because it doesn't have an "alone" 8 value
If we searched for just 100 it would return that last record.
This function comes at a cost of performance on large datasets; which if data was normalized and indexed, you wouldn't have.
So why does this exit? For small enumerated lists or properties. It's still not ideal but if you have just a few using it "can" make sense. but in a very limited use case and often is missused.
This design violates 3rd normal form. Which is why most RDBMS designs cringe when it's brought up as it's not scalable.
as to why people are up in arms about multi value columns: Read this or This
You can also use rlike and in fact it is much better than like as it has much more options.
* = repetition of what is in front of it zero or more times
. = Equivalent to any character including none
^ = Anchor start (Forces that begins with ...)
$ = final anchor (forces it to end with ....)
[ ] = [ RST ] Contain an R or S or T but only one
[^] = DENY IT
And many more options
select * from style where concat(',',categories,',') rlike '*,8,*';

My SQL query not retrieving all the data from the database

I have a table in my database with the name contact. It has the following columns: name, mobile and twon. The problem is that I'm trying to get all the twon='Dubai', but when I execute my query it only retrieves 81000 rows but the total was 130000. The other remaining rows are not appearing in my query.
My Query:
SELECT * FROM `contact` WHERE `twon` = 'Dubai'
Can anyone tell me where I am going wrong or help me to access all the data from table?
= will fetch the record only if the column value is exactly 'dubai'.
Try with LIKE,TRIM and LOWER:
SELECT * FROM `contact` WHERE LOWER(TRIM(`twon`)) LIKE '%dubai%'
This query will fetch the records if twon column contains the word 'dubai'.
Different things could be wrong.
If you post examples of rows that should be returned, it would help us.
Case Sensitivity
If case sensitivity is a problem (e.g. 'dubai' or 'DUBAI' are not returned), you can use the LOWER function
SELECT * FROM `contact` WHERE LOWER(`twon`) = 'dubai'
Extra blanks
In some cases, extra blanks in the column content would fail, for instance ' Dubai' and ' Dubai '. You can use the TRIM function to get rid of trailing and leading blanks.
SELECT * FROM `contact` WHERE TRIM(`twon`) = 'Dubai'
Combination
Combining the two will work, too.
SELECT * FROM `contact` WHERE LOWER(TRIM(`twon`)) = 'dubai'

MySQL returns all rows when field=0 from SECOND Select query

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.)

MySql: Calculate a value based on multiple sub-queries

I have a query that calculates a value based on several sub-queries. The sub-queries are based on a specific timestamp. I would like to calculate this value for records for many different timestamps. I can't quite figure out how to do it.
The basic formula is (S11S4CreateSessionReqRcvd - S11S4CreateSessionRespAccSent) * 100 / S11S4CreateSessionRespAccSent
SELECT
((((select ref_data FROM test.sgw_S5S11 where timestamp = "2013-08-21 00:00:06" and ref_type = "S11S4CreateSessionReqRcvd" ) - (select ref_data FROM test.sgw_S5S11
where timestamp = "2013-08-21 00:00:06" and ref_type = "S11S4CreateSessionRespAccSent")) * 100) / (select ref_data FROM test.sgw_S5S11
where timestamp = "2013-08-21 00:00:06" and ref_type = "S11S4CreateSessionReqRcvd")) as MyCalc
I don't know how to paste in a table so here's a sample of my data in csv format
Here's a sample of my data. (I don't know how to put a table in here so it's in CSV format)
mykey,timestamp,ref_type,ref_data 1016101,"2013-08-21 00:00:06",S5S8CreateSessionReqSent,128042907 1016102,"2013-08-21 00:00:06",S5S8CreateSessionRespAccRcvd,127088838 1016103,"2013-08-21 00:00:06",S5S8CreateSessionRespRejRcvd,615553 1016104,"2013-08-21 00:00:06",S5S8CreateBearerReqRcvd,10047 1016105,"2013-08-21 00:00:06",S5S8CreateBearerRespAccSent,9932 1016106,"2013-08-21 00:00:06",S5S8CreateBearerRespRejSent,103 1016107,"2013-08-21 00:00:06",S11S4CreateSessionReqRcvd,128255390 1016108,"2013-08-21 00:00:06",S11S4CreateSessionRespAccSent,127114539 1016109,"2013-08-21 00:00:06",S11S4CreateSessionRespRejSent,713325 1016110,"2013-08-21 00:00:06",S11S4CreateBearerReqSent,10028 1016111,"2013-08-21 00:00:06",S11S4CreateBearerRespAccRcvd,9932 1016112,"2013-08-21 00:00:06",S11S4CreateBearerRespRejRcvd,42
Any help would be greatly appreciated!!!
This query is awkward because you have stored attributes on separate rows. This design is called Entity-Attribute-Value, and it's usually a bad idea for a relational database.
The following query might be a little more efficient and easier to write:
SELECT (eav.ReqRcvd - eav.AccSent) * 100 / eav.AccSent AS MyCalc
FROM (
SELECT timestamp,
MAX(IF(ref_type='S11S4CreateSessionReqRcvd', ref_data)) AS ReqRcvd,
MAX(IF(ref_type='S11S4CreateSessionRespAccSent', ref_data)) AS AccSent
FROM test.sgw_S5S11
WHERE timestamp = '2013-08-21 00:00:06'
GROUP BY timestamp
) AS eav;
PS: Use single quotes ' for string and date literals, not double quotes ". In standard SQL, double quotes are for delimiting table and column identifiers. MySQL treats the two types of quotes the same by default, but this is subject to SQL_MODE and also won't behave the same way if you ever use another brand of RDBMS. So it's a good to develop the habit of using quotes in the standard way.

Is OK to enclosing all values in SQL statement with single quotes?

Is it ok to enclose all values in SQL statement with single quotes ? For example:
This is simple table called books:
id | title
1 | Some book name
2 | Second book name
Is it OK to write statement like this:
SELECT * FROM books WHERE id = '1'
I've tested that query in SQL server 2008 and MySQL 5 and it works good, but I am curious is there any performance issue, because ID field is acctualy integer.
And second question is it OK to write statement like this:
SELECT * FROM books WHERE id = N'1'
N prefix is used in SQL server for UTF-8 fields, but I've tested that in SQL server and MySQL and both worked OK. I don't know if SQLite support N prefix, because I didn't test that.
The reason why I am asking this is because I am building database class that will work with popular SQL databases (SQL Server, MySQL, SQLite and maybe MS Access), so when performing selecting, inserting or updating data I don't have to worry about field datatype. I can always enclose value with N'Some value', but I am curious is this correct and is there any performance issues?
In SQL Server, you can get an implicit conversion when doing this. Sometimes it won't affect the plan or have noticeable impacts on performance, but sometimes it might. They are generally deemed to be bad. Inspect the plans for these two queries against AdventureWorks2012:
SELECT * FROM Sales.SalesOrderHeader WHERE SalesOrderID = 43659;
SELECT * FROM Sales.SalesOrderHeader WHERE SalesOrderID = '43659';
The latter contains a CONVERT_IMPLICIT (hover over the tooltip for the CI seek).
You also want to be very careful about switching between VARCHAR and NVARCHAR - in some cases this can be dreadful for performance, depending on the underlying data type and whether the literal has the N prefix.
Long story short: don't do this. Write your ORM thingy so that it understands the different data types and handles them appropriately.
SELECT ... WHERE int_type = '123' is fine to do. SQL will convert '123' to an integer once and be done with it.
However, SELECT ... WHERE char_type = 123 is no okay, because SQL will have to convert every cell into an integer. See that char_type = '0123' and char_type = '00123' will also match. So it has to do more work.
Thanks to #MartinSmith for pointing out a resource for precedence in casting: http://msdn.microsoft.com/en-us/library/ms190309.aspx
Here's an example bug in MySQL that says the implicit typecast from quoted string of digits to an integer causes a severe performance issue: http://bugs.mysql.com/bug.php?id=43319
It's best to not quote numbers.
SQL Server and MySQL both perform implicit type conversions, but it doesn't make it a good practice; use the appropriate native type when you can. This will let you avoid trying to spot the difference between:
SELECT * FROM books WHERE id = '1'
and
SELECT * FROM books WHERE id = 'l'
and
SELECT * FROM books WHERE id = 'O'
and
SELECT * FROM books WHERE id = '0'
(that's a one, a lower case L, a capital 'o', and a zero respectively)