from and to ranges in mysql - mysql

Currently I have this kind of query
SELECT
part_number,
part_name,
attenuation_low_end,
attenuation_high_end,
optimum_fermentation_temp_f_low,
optimum_fermentation_temp_f_high
FROM
yeast_module
WHERE
category = 3
AND
(
( `attenuation_low_end` > '31' OR `attenuation_low_end` = '31' )
AND
( `attenuation_high_end` < '40' OR `attenuation_high_end` = '40' )
)
Where I'm trying to get the records with the range of low to high end from 31 and maximum of 40
But it returns me something like this
As you can notice it seems doesn't return the data between 31 to 40
Am I doing this right?
UPDATE
I'm expecting no return since, there's no data between 31-40

You're comparing strings, which performs lexicographic comparisons rather than numeric comparisons. You need to convert to numbers. Adding 0 to a numeric string is a simple way to convert it to a number.
WHERE 0+attenuation_low_end >= 31 AND 0+attenuation_high_end <= 40

If you want ranges contained in the 31-40 range:
where attenuation_low_end >= 31 and attenuation_high_end <= 40
If you want ranges that overlap the 31-40 range:
where attenuation_low_end <= 40 and attenuation_high_end >= 31
If your data is of a string datatype, then you need to convert the values to integers so they can be compared as such.
Containment:
where attenuation_low_end + 0 >= 31 and attenuation_high_end + 0 <= 40
Overlap:
where attenuation_low_end + 0 <= 40 and attenuation_high_end + 0 >= 31

Related

SQL - Calculate two fields in one Case

I have a sql query that calculates a field as follows:
Select
Case When b.xField > 10
then 20
when b.xField > 48
then 10
else 0
end as field1
from (Select CASE WHEN numberChosen < 15
THEN 10
WHEN numberChosen > 15
THEN 48
END as xField
From secondTable) B
What I need is, when field1 is 10, then do some other calculations to save on another field.
Example something like:
then 20 AND field2 = yData - 26
so when the case is on 20, then have another field equal to yData - 26.
Can that be achieved using Cases in Sql ? Have two fields calculated in a single case?
I want to calculate two fields in one Case
You Can't Do Thatâ„¢.
You can put two case clauses in your query like this:
Select
Case When xField > 10
then 20
when xField > 48
then 10
else 0
end as field1,
Case When xField > 10
then ydata - 26
else 0
end as field2
from myData
Or you can generate the extra field value in a wrapper query if it is really hard to compute field2
SELECT field1, CASE WHEN field1 > 10 THEN ydata -20 ELSE 0 END field2
FROM (
Select
ydata,
Case When xField > 10
then 20
when xField > 48
then 10
else 0
end as field1
from myData
) subquery
You can use the base logic that is deciding when field1 = 10 (ie. xField > 48) in the second case:
SELECT CASE WHEN xField > 48
THEN 10
WHEN xField > 10
THEN 20
ELSE 0
END as field1,
CASE WHEN xField > 48
THEN yData - 26
END as field2
FROM (SELECT CASE WHEN numberChosen < 15
THEN 10
WHEN numberChosen > 15
THEN 48
END as xField,
yData
FROM secondTable) B
I changed the order of your case because putting the > 10 condition before the > 48 condition will never let the > 48 be hit.

Datediff in MsAccess

I am stuck in one place.
I am using DateDiff in Ms Access it is giving me proper output, like
StartDate is 10-Sep-2016
EndDate is 15-Oct-2016
Total Days which I will get is 35
& months will i get is 1 Month
DateDiff('d',StartDate,EndDate)
**But I want output as 2 months if it is exeeded the 30 days.
if it is 61 days then 3 months & so on.
**IIFFF days diffrence is
29 Days then output should be 1 months
30 Days then output should be 1 months
32 Days then output should be 2 months
60 Days then output should be 2 months
62 Days then output should be 3 months**
Will that be possible in the DateDiff in MsAccess
or is there any other function available so that i can achieve the same output.**
You can do this using conditional logic. Perhaps something like this:
select iif(DateDiff('d', StartDate, EndDate) > 30,
DateDiff('d',StartDate,EndDate) & " days",
"2 months"
)
Your logic that anything exceeding 30 days is "2 months" seems strange. Normally, I think the logic would look like this:
select iif(DateDiff('d', StartDate, EndDate) > 30,
DateDiff('d', StartDate, EndDate) & " days",
DateDiff('m', StartDate, EndDate) & " months"
)
will this logic suffice to modify your SQL function?
Public Function FN_GET_MONTH(iDays As Long, Optional iDaysInMonth As Long = 30)
If (iDays / iDaysInMonth) > iDays \ iDaysInMonth Then
FN_GET_MONTH = (iDays \ iDaysInMonth) + 1
Else
FN_GET_MONTH = (iDays \ iDaysInMonth)
End If
End Function
?FN_GET_MONTH(29) = 1
?FN_GET_MONTH(31) = 2
?FN_GET_MONTH(60) = 2
?FN_GET_MONTH(80) = 3
?FN_GET_MONTH(91) = 4
you can have this public function and use it in your SQL code like
FN_GET_MONTH(DateDiff("d", StartDate, EndDate))
This query seems to give the results you seek:
SELECT
StartDate,
EndDate
numDays,
((numDays - 1) \ 30) + 1 AS numMonths
FROM
(
SELECT
StartDate,
EndDate,
DateDiff("d", StartDate, EndDate) AS numDays
FROM YourTable
)
It gives me
numDays numMonths
------- ---------
...
29 1
30 1
31 2
32 2
...
59 2
60 2
61 3
62 3
...
It seems like your minimum count of months for a positive count of days is 1, thus:
MonthCount = Sgn(DateDiff("d",StartDate,EndDate)) + DateDiff("m",StartDate,EndDate)
Edit
For a 30-day cut that will produce your example output, use this simple formula in your query:
MonthCount: (DateDiff("d",[StartDate],[EndDate])-1)\30+1

How to write a MySQL statement with multiple conditionals?

I have the following table:
id (integer, primary key)
amount_low (integer)
amount_high (integer)
fixedprice (decimal 4,2 Null)
percentadjust (decimal 4,2 Null)
itemname (varchar 50)
A record will have a value in either the "fixedprice" or "percentadjust" field, but not both. One will be NULL, and the other will have a value.
I need to get records based on a single input amount, "X":
If the "fixedprice" field has a value, I need to get the record if X is >= (fixedprice * amount_low) AND X is <= (fixedprice * amount_high).
If the "percentadjust" field has a value, I need to get the record if X is >= ((((percentadjust / 100) + 1) * 3.5) * amount_low) AND X is <= ((((percentadjust / 100) + 1) * 3.5) * amount_high).
The "3.5" is a value that changes on occasion and I'm not too concerned about that part.
What is a good way to do this in MySQL?
Sample data: (also see http://sqlfiddle.com/#!9/922a0 )
id amount_low amount_high fixedprice percentadjust itemname
-----------------------------------------------------------------
1 20 25 2.25 NULL A
2 50 75 2.38 NULL B
3 23 32 NULL 9.75 C
4 14 22 NULL 9.12 D
5 96 112 2.58 NULL E
Assuming your X was entered as 111 it would be
select * from tblItems
where (fixedprice is not null and 111>=(fixedprice * amount_low) and 111 <= (fixedprice * amount_high) )
OR (percentadjust is not null and 111>=((((percentadjust / 100) + 1) * 3.5) * amount_low) AND 111<=((((percentadjust / 100) + 1) * 3.5) * amount_high))
Note you can always write it as where xyz between A and B to simplify somethings slightly.
Remember that a lot of time can be wasted debugging logic operators when AND and OR are used and safe wrappers with parentheses are not used. So, if you intermingle AND with OR, wrap things well.

mysql between show matched value

I have a table with columns showing ranges, like
id from to
1 10 100
2 200 300
I have a query which will be a list of values, like 17, 20, 44, 288 etc.
Is it possible to have a result set which would include the where condition, so I get:
id from to input
1 10 100 7
1 10 100 20
1 10 100 144
2 200 300 288
Right now the code runs one query per where value and it works, and I'm looking to increase performance by combing it into one large multiple where clause, like
SELECT *
FROM table
WHERE (from<=7 AND start>=7)
OR (from<=20 AND start>=20)
OR (from<=144 AND start>=144)
OR (from<=288 AND start>=288)
What you want makes no sense regarding ranges.
7 and 144 has no compatible range yet you want to put then into the first range.
In a result set with lots of values listing you will probably get to many conditions.
What you can do is to put those values that isn't in a range to show without correspondence. Like this:
With the structure being:
create table test (
id integer,
vfrom integer,
vto integer
);
insert into test values
(1, 10, 100),
(2, 200, 300);
create table vals(
val integer
);
insert into vals values (7), (20), (144), (288);
You can use this query:
select val, id, vfrom, vto
from vals v left join
test t on ( t.vfrom <= v.val and t.vto >= v.val )
It will bring you:
7 null null null
20 1 10 100
144 null null null
288 2 200 300
see it here on fiddle: http://sqlfiddle.com/#!2/f68fd/8
Maybe it isn't what you want but it is more logical.
Sure there is a query for this. Trouble is we need a table for specific values to show up; and then there are sub-queries and union selects:
SELECT table.*, values.val AS input
FROM (SELECT 7 AS val UNION SELECT 20 AS val UNION SELECT 144 AS val UNION SELECT 288 AS val) as values
JOIN table ON table.from <= values.val AND table.to >= values.val
This should do the trick. Note that you only have to specify the column name in the first SELECT with in a UNION SELECT.
I will suppose you are using Java as your application language. You could build your query this way:
public String buildQuery(int[] myList) {
String queryToReturn = "";
for (int queryIndex = 0; queryIndex < myList.length; queryIndex++) {
queryToReturn += ((queryIndex == 0) ? ("") : (" union ")) +
"(select `id`, `from`, `to`, " + myList[queryIndex] + " as input
from MyTable
where `from` < " + myList[queryIndex] + " and " + myList[queryIndex] " < `to`)";
}
return queryToReturn;
}
Then run the returned query.

Convert and round (Seconds to Minutes) with SQL

I have a field on my table which represents seconds, I want to convert to minutes
Select (100/60) as Minute from MyTable
-> 1.66
How can I get 1 minute and 40 seconds 00:01:40 and then round to 00:02:00 and if 00:01:23 round to 00:01:30
Using Mysql.
There are two ways of rounding, using integer arithmetic and avoiding floating points, a value to the nearest thirty seconds...
((seconds + 15) DIV 30) * 30
(seconds + 15) - (seconds + 15) % 30
The latter is longer, but in terms of cpu time should be faster.
You can then use SEC_TO_TIME(seconds) to get the format hh:mm:ss, and take the right 5 characters if you really need hh:mm.
If you wanted to avoid SEC_TO_TIME(seconds), you can build up the string yourself.
minutes = total_seconds DIV 60
seconds = total_seconds % 60
final string = LPAD(minutes, 2, '0') | ':' | LPAD(seconds, 2, '0')
i am not sure about how to round it but you can convert seconds into time i.e hh:mm:ss format using SEC_TO_TIME(totaltime)
Desired result :
A = 30
B = 60
C = 90
D = 120
select
(25 + 15)-(25 + 15) % 30 as A,
(32 + 15)-(32 + 15) % 30 as B,
(90 + 15)-(90 + 15) % 30 as C,
(100 + 15)-(100 + 15) % 30 as D
Result :
A = 30
B = 30
C = 90
D = 90
I try with this:
select
30* ceil(30/30) as A,
30* ceil(32/30) as B,
30* ceil(90/30) as C,
30* ceil(100/30) as D
Result :
A = 30
B = 60
C = 90
D = 120
Thank you for your help !
You can simply write your own function http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
But I'd rather do that in a programing language (PHP, Python, C), not on the database side.