What is the equivalent of Select Case in Access SQL? - ms-access

I have a query which includes fields named openingbalance and commissions. I would like to compute values for commissions based on openingbalance, similar to this Select Case block in Access VBA:
Select Case OpeningBalance
Case 0 To 5000
commission = 20
Case 5001 To 10000
commission = 30
Case 10001 To 20000
commission = 40
Case Else
commission = 50
End Select
But since Access doesn't allow Select Case in a query, how can I accomplish my goal in Access SQL?

Consider the Switch Function as an alternative to multiple IIf() expressions. It will return the value from the first expression/value pair where the expression evaluates as True, and ignore any remaining pairs. The concept is similar to the SELECT ... CASE approach you referenced but which is not available in Access SQL.
If you want to display a calculated field as commission:
SELECT
Switch(
OpeningBalance < 5001, 20,
OpeningBalance < 10001, 30,
OpeningBalance < 20001, 40,
OpeningBalance >= 20001, 50
) AS commission
FROM YourTable;
If you want to store that calculated value to a field named commission:
UPDATE YourTable
SET commission =
Switch(
OpeningBalance < 5001, 20,
OpeningBalance < 10001, 30,
OpeningBalance < 20001, 40,
OpeningBalance >= 20001, 50
);
Either way, see whether you find Switch() easier to understand and manage. Multiple IIf()s can become mind-boggling as the number of conditions grows.

You can use IIF for a similar result.
Note that you can nest the IIF statements to handle multiple cases. There is an example here: http://forums.devshed.com/database-management-46/query-ms-access-iif-statement-multiple-conditions-358130.html
SELECT IIf([Combinaison] = "Mike", 12, IIf([Combinaison] = "Steve", 13)) As Answer
FROM MyTable;

You could do below:
select
iif ( OpeningBalance>=0 And OpeningBalance<=500 , 20,
iif ( OpeningBalance>=5001 And OpeningBalance<=10000 , 30,
iif ( OpeningBalance>=10001 And OpeningBalance<=20000 , 40,
50 ) ) ) as commission
from table

Related

How I can get limit_exceded value if value is less than or greater than in "limit_exceded" column i would get 1 else 0 in mysql

database table_img for better understanding
Pardon me for weak English writing
my sql query that i am getting value,low_value,high_value and limit_exceded_. issue is in limit_exceded to not get correct values, it shows all 0.
SELECT `myvalues`.`value`, `sub_types`.`low_value`, `sub_types`.`high_value`,
(case when myvalues.value > sub_types.low_value and myvalues.value < sub_types.high_value then 1 else 0 end) as limit_exceded
FROM `myvalues`
JOIN `sub_types` ON `myvalues`.`sub_type_id` = `sub_types`.`id`
WHERE `myvalues`.`sub_type_id` IN('68')
AND `myvalues`.`observation_id` IN('455', '471', '470', '469', '468', '467', '466', '465', '462', '461', '460', '459', '458', '457', '456', '372', '453', '373', '376', '439', '440', '441', '442', '443', '445', '446', '447', '448', '452', '454')
I want to get int 1 in front of those values whose value is less than 40 or greater than 180. Also it would it be appreciated if extract max and min from this list and count limit_exceded values
expected result is set value 1 where values is 900,9 and 1 etc
issue is in limit_exceded to not get correct values, it shows all 0
I suspect the issue is the types. The way the data lines up in the image and the use of strings in the WHERE clause suggest that the values are strings not numbers. A simply way to convert is to use + 0:
SELECT v.value, st.low_value, st.high_value,
(v.value + 0) > (st.low_value + 0) and (v.value + 0) < (st.high_value + 0) as limit_exceded
FROM myvalues v JOIN
sub_types st
ON v.sub_type_id = st.id
WHERE v.sub_type_id IN ('68') AND
v.observation_id IN ('455', '471', '470', '469', '468', '467', '466', '465', '462', '461', '460', '459', '458', '457', '456', '372', '453', '373', '376', '439', '440', '441', '442', '443', '445', '446', '447', '448', '452', '454')
Notes:
Table aliases make the query easier to write and to read.
Unnecessary backticks just make the query harder to write and to read.
In MySQL, you don't need the CASE expression -- you can just use the boolean expression.
That said, you should fix the data, not the query. If the values are numbers, store them as numbers, not string.

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.

Fastest way to calculate correlation in every row?

Well, I have a table data of millions of rows. I want to carry out correlation study for every row (from the 1st to the current row minus 1). For e.g. the 1st rows is omitted. The 2nd row's result column is to be supplied with the correlation using the 1st row. The 3rd row's result column is to be supplied with the correlation using the 1st and 2nd row. And so on.
Correlation for the entire table can be calculated using:
SELECT (Count(*)*Sum(x*y)-Sum(x)*Sum(y))/
(sqrt(Count(*)*Sum(x*x)-Sum(x)*Sum(x))*
sqrt(Count(*)*Sum(y*y)-Sum(y)*Sum(y))) AS TotalCorelation FROM Data;
I want to avoid using Joins as much as possible as it takes lots of time, sometimes even timeout error, above 300 seconds). What's the other alternative?
Example table Data Structure:
id, x, y, result
1 , 4, 2, null
2 , 6, 3, -0.2312
3 , 5, 5, 0.42312
4 , 6, 2, -0.5231
5 , 5, 5, 0.22312
6 , 3, 7, -0.2312
7 , 2, 9, 0.42231
8 , 7, 2, 0.32253
9 , 9, 5, 0.32431
id : primary key
x and y : The data
result: correlation
I think this is it:
SELECT d2.ID, d2.x, d2.y, d2.result,
(Count(*)*Sum(d1.x*d1.y)-Sum(d1.x)*Sum(d1.y))/
(sqrt(Count(*)*Sum(d1.x*d1.x)-Sum(d1.x)*Sum(d1.x))*
sqrt(Count(*)*Sum(d1.y*d1.y)-Sum(d1.y)*Sum(d1.y))) AS TotalCorelation
FROM Data d1
RIGHT JOIN Data d2 ON d1.id < d2.id
GROUP BY d2.ID
ORDER BY d2.ID
Without a closed form for calculating correlation of N+1 from N rows, you have to use a quadratic join like this.
I'm assuming that your basic formula is correct. But I'm not sure it is -- when I just run it on the total dataset, I don't get the result 0.32431, I get -0.552773693079.
Here's a linear implementation:
SET #SumX = 0;
SET #SumY = 0;
SET #Count = 0;
SET #SumX2 = 0;
SET #SumY2 = 0;
SET #SumXY = 0;
SELECT id, x, y,
#SumX := #SumX + x AS SumX,
#SumY := #SumY + y AS SumY,
#Count := #Count + 1 AS ct,
#SumX2 := #SumX2 + x*x AS SumX2,
#SumY2 := #SumY2 + y*y AS SumY2,
#SumXY := #SumXY + x*y AS SumXY,
IF(#Count > 1,
(#Count*#SumXY-#SumX*#SumY)/
(sqrt(#Count*#SumX2-#SumX*#SumX)*
sqrt(#Count*#SumY2-#SumY*#SumY)), NULL) AS TotalCorelation
FROM DATA
ORDER BY id
SQLFIDDLE

Available Filters With Specified Ranges In SSRS

I am working on a Chart in my report.
As I have too many records where CountId = 1, I have set up a filter showing an available values list like this:
CountId :
1
2
3
Between 4 to 6
Between 7 to 9
Above 10
If I set the available value 1 or 2 or 3 it shows results, but I don`t know how to set a filter for between and above.
I want a filter some thing like this - available filters are:
1
2
3
4
Above 5 or greater than equal to 5
You've got a mix of operators, so maybe you should look at an expression based filter to try and handle these different cases, something like:
Expression (type Text):
=Switch(Parameters!Count.Value = "1" and Fields!Count.Value = 1, "Include"
, Parameters!Count.Value = "2" and Fields!Count.Value = 2, "Include"
, Parameters!Count.Value = "3" and Fields!Count.Value = 3, "Include"
, Parameters!Count.Value = "4 to 6" and Fields!Count.Value >= 4 and Fields!Count.Value <= 6, "Include"
, Parameters!Count.Value = "7 to 9" and Fields!Count.Value >= 7 and Fields!Count.Value <= 9, "Include"
, Parameters!Count.Value = "Above 10" and Fields!Count.Value >= 10, "Include"
, true, "Exclude")
Operator:
=
Value:
Include
This assumes a string parameter Count populated with the above values.
This works by calculating the parameter and field combinations to produce a constant, either Include or Exclude, then displaying all rows that return Include.
As mentioned in a comment, it's difficult to follow exactly what you're asking here. I've done my best but if you have more questions it would be best to update the question with some sample data and how you'd like this data displayed.

Concat different tables?

I need to concatenate from two different tables.
Compare s.panelid (result like "AA") to b.modulecodes and return number_of_strings. Then put s.panelid (result like "AA") and number_of_string together.
select concat(Mid(s.panelid, 5, 2), ' - ' , '??') as `Module Type-Strings`
from r2rtool.stringtopanel s, be.modulecodes b
where s.insertts > '2011-07-15' and s.insertts < '2011-07-26' and Mid(s.panelid, 5, 2) != 99
group by date(insertts), `Module Type-Strings`
order by `Module Type-Strings`;
Be (Table): modulecodes, number_of_strings
AA - 12
AB - 4
AD - 3
AE - 12
When I run the above query it returns things like: Module Type-Strings = 'AA-??' and "AB-??" of course.
I am looking for: Module Type-Strings = 'AA-12'
Just in case you haven't tried it already...
Have you tried this?
select concat(Mid(s.panelid, 5, 2), ' - ' , b.number_of_string) as `Module Type-Strings`
from r2rtool.stringtopanel s, be.modulecodes b
where s.insertts > '2011-07-15' and s.insertts < '2011-07-26' and Mid(s.panelid, 5, 2) != 99
group by date(insertts), `Module Type-Strings`
order by `Module Type-Strings`;
There I'm basically replacing the '??' with the column you are asking about, number_of_string in the be.modulecodes table (aliased as b in the from clause).