Rounding a field's value in a SELECT statement - c#

What I need to do is to round a field to 2 decimals, but not in the usual way. I have a dropdown that's always rounded to 2 decimals (CIT_NBR). However, in the database table, it's sometimes rounded to 1 decimal. So now I'm trying to create a SELECT statement based on this field, but my front end stores it as 2 decimals and my back end can be stored as either 1 or 2 decimals. Don't ask, it's complicated. :o)
So, what I want to do in "aircode" is something like:
SELECT * FROM VW_MOS_DPL_AccountValidation WHERE CUST_NUM = #CNum
AND Format(CIT_NBR, 2 decimals) = #CITNum
This way, it forces the data in the table to use 2 decimals, so it can be compared to my dropdown.
Here's my code block:
using (SqlConnection con2 = new SqlConnection(str2))
{
using (SqlCommand cmd2 = new SqlCommand(#"SELECT * FROM VW_MOS_DPL_AccountValidation WHERE CUST_NUM = #CNum AND CIT_NBR = #CITNum", con2))
{
con2.Open();
cmd2.Parameters.AddWithValue("#CNum", TBAccountNum.Text);
string ddlCITVal2 = ddlCIT.SelectedValue;
cmd2.Parameters.AddWithValue("#CITNum", ddlCITVal2);
using (SqlDataReader DT2 = cmd2.ExecuteReader())
{
// If the SQL returns any records, process the info
if (DT2.HasRows)
{
while (DT2.Read())
{
.
.
.
etc
How could I go about doing this?

Cast the varchar to a decimal
SELECT SUM(Cast(CitNum as decimal(8,2))) as CitNum FROM table

There is a more performant approach, but this is easiest to read and maintain unless it causes a real performance problem.
SELECT *
FROM VW_MOS_DPL_AccountValidation
WHERE CUST_NUM = #CNum
AND (CIT_NBR=#CITNUM OR CIT_NBR+'0'=#CITNUM)
Unless you really meant rounded to one decimal instead of the example you gave which is just truncating a trailing zero, in which case a different approach would need to be used.

Related

How to get the average of a column in MySQL

I'm trying to find a way to calculate the average of a column (as a double/float or decimal). I've found the AVG function in MySQL documentation but I can't get it to work. Currently I've got the following code:
public double GetRating(string username)
{
double average;
MySqlConnection databaseConnection = new MySqlConnection(connectionString);
string sumQuery = "select sum('rating') from " + username;
string countQuery = "SELECT COUNT(*) FROM " + username;
using (MySqlCommand sumCommand = new MySqlCommand(sumQuery, databaseConnection))
using (MySqlCommand countCommand = new MySqlCommand(countQuery, databaseConnection))
try
{
databaseConnection.Open();
double sum = (Double)sumCommand.ExecuteScalar();
double columnLength = (Double)countCommand.ExecuteScalar();
average = sum / columnLength;
return average;
}
finally
{
databaseConnection.Close();
}
return average;
}
Now for some reason this does not work. It returns "Unable to cast object of type 'System.Int64' to type 'System.Double'."
The stored data in the database is an int but i'm trying to cast them to double. Any suggestions or solutions? Once again; double/float or decimal are usable for me.
The built-in AVG function (an aggregate function) could be used like so:
select avg(rating) from table_name
Note that, like most aggregate functions, the average will exclude null values (the average of 1, 2, null is 1.5 instead of 1.0). Also, in MySQL the return datatype will be decimal if you're averaging decimal or integer columns so use the appropriate C# datatype.
A couple of things:
What is the data type of the rating column in the table? If it is an integer and not floating-point, please change the data type of sum accordingly to avoid the type-cast error.
As you already know, you may use avg() instead of sum() and then division by count(). Your SQL will look like:
select avg(rating) from table_name

How to perform addition to number rather than appending to end in Linq

Trying to update a table in ASP.net MVC with a Linq query. It works fine in terms of actually doing the update, but I can't figure out how to mathematically update it. For example, the Printer Credit Fund was set to "50", added 12 to it then sets it "5012" as opposed to "62". The following is the code that is doing the update:
tblOption fund = (
from n in db.tblOptions
where n.ID == 1
select n).First();
fund.PrinterCreditFund = fund.PrinterCreditFund + tblPrinterCredit.Money;
We're using Entity Framework if that makes any sort of a difference.
Any tips towards the right direction of doing a mathematical update rather than appending the value would be hugely appreciated.
Many thanks
That's it. Convert fund.PrinterCreditFund and tblPrinterCredit.Money to using Convert.ToInt32() and also make sure fund.PrinterCreditFund is also int type
tblOption fund = (
from n in db.tblOptions
where n.ID == 1
select n).First();
fund.PrinterCreditFund = Convert.ToInt32( fund.PrinterCreditFund) + Convert.ToInt32( tblPrinterCredit.Money);
I guess that either Money is a string. Then the + operator concats them instead of summing the values. So both must be a numeric type, for example int:
fund.PrinterCreditFund = fund.PrinterCreditFund + int.Parse(tblPrinterCredit.Money);
Of course it would be better to not store a number as string in the first place.

Double precision error when getting data from SQL server

I'm trying to get an real number from an SQL view.
But after executing the query it will round the number from 6728873.3 to 6728873.5
Why is this happening and is there any way around this?
I have tried getting the data with a DataReader, Linq2SQL and ServiceStack.ORMLite but none of them work.
var lConnection = new SqlConnection(ConnectionString);
const string cmd = "SELECT [Origin],[X],[Y] FROM [SpiderDB61].[dbo].[View_Addresses_AddressNames]" +
" where Origin = 5 and X = -26262.5 and Y = 6728873.3";
var lSQLCommand = new SqlCommand(cmd, lConnection);
lConnection.Open();
SqlDataReader lReader = lSQLCommand.ExecuteReader();
object a;
object b;
object c;
while (lReader.Read())
{
a = lReader[0];
b = lReader[1];
c = lReader[2]; // <-- this will be 6728873.5, not 6728873.3
}
real is float(24), which gives you approximately 7 digits of precision. 6728873.3 is 8 digits. Basically, you are at the limit of what is reliable / precise for real. You should consider a different data type; perhaps float (which defaults to float(53)), perhaps decimal(x,y) - depending on whether this value is meant to be discreet or continuous.

Padding 0's - MySQL

So, I have a column that is my key column and auto-increments, so it can't be varchar or anything fun.
Please hold back the "Erhmahgerd urse werb contrerls" as I like to control my own HTML flow and don't like handing it over to .NET. I've never had good experiences with that (and I like my code to be compliant). I wouldn't like this to be a flame war or anything - I just want to pad with zeroes. I feel the need to say this because it's happened way too many times before.
So, anyway.
DataTable tabledata = new DataTable();
using (OdbcConnection con = new OdbcConnection(conString)) {
using (OdbcCommand com = new OdbcCommand("SELECT * FROM equipment_table", con)) {
OdbcDataAdapter myAdapter = new OdbcDataAdapter();
myAdapter.SelectCommand = com;
try {
con.Open();
myAdapter.Fill(tabledata);
} catch (Exception ex) {
throw (ex);
} finally {
con.Close();
}
}
}
Response.Write("<table id=\"equipment_listtable\"><thead><tr><th>Equipment ID</th><th>Equipment Name</th><th>Equipment Description</th><th>Type</th><th>In Use?</th><th>iOS Version (if applicable)</th><th>Permission Level</th><th>Status</th><th>Asset Tag</th><th>Details</th><th>Change</th><th>Apply</th></tr></thead>");
foreach (DataRow row in tabledata.Rows) {
int counter = (int)row["Equipment_ID"];
Response.Write("<tr>");
foreach (var item in row.ItemArray) {
Response.Write("<td>" + item + "</td>");
}
Response.Write("This stuff is irrelevant to my problem, so it is being left out... It uses counter though, so no complaining about not using variables...");
}
Response.Write("</table>");
As you can imagine, the value of my key column comes out like so in the generated table:
1
10
11
12
13
14
15
16
17
18
19
20
2
21
etc. I'd like to fix this with 0 padding. What is the best way to do this? Is there a way to target a SPECIFIC field while I'm generating the table? I've looked into DataRow.Item, but I've always found the MSDN documentation to be a bit difficult to comprehend.
Alternatively, could I SELECT * and then use mysql's lpad on ONE specific field within the *?
Thanks!
SELECT * is generally not a good idea to use. It inevitably causes more problems than the time it saves by writing the query.
This will allow you to use a LPAD on the column.
I was about to suggest using something like:
Response.Write("" + item.ToString.PadLeft(2, '0')+ "");
But since you are just looping round each item and rendering them all the same way, the above would pad every cell.
So I think your best option is to change your query to specify every column. Then you can pad the field as you want.
Or use an ORDER BY if you are only concerned they aren't being ordered correctly (ie, ordered as chars not ints).
alternatively, create a variable for each cell read from the database and render each seperately.
this will give you more customisation options, should you requite them.
You really should always specify your column names explicitly and not use * anyway - see here.
If you insist on using * then just bring the padded value in as another field:
SELECT *,LPAD("Equipment_ID", 2, '0') as Equipment_ID_Padded FROM equipment_table
Remember LPAD will truncate if your Equipment_ID is longer than 2 digits.
A better solution may be to just pad the values in code using String.Format or ToString("D2");
string paddedString = string.Format("{0:d2}", (int)row["Equipment_ID"]));
You can add padding in C# by using .ToString("D" + number of leading zeros);
eg. if counter = 34 and you call counter.ToString("D5"), you'll get 00034.
If you're using strings, the easiest way would be to convert.toInt32() and then apply the above.
If you'd rather keep using strings, just look into --printf whups wrong language-- String.Format.

Use of unassigned local variable at run time

wpf application actually I create account application I went display opening amt. opening amt equal to dr_amt-cr_amt . dr_amt and cr_amt is column name of amt table there for i can do
double a, b, c;
SqlConnection con = new SqlConnection("my conn");
SqlCommand cmd = new SqlCommand("select sum(dr_amt),sum(cr_amt) from amt where id='"+tex1.Text+"'", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
a = Convert.ToDouble(dr[0]);
b = Convert.ToDouble(dr[1]);
}
c = a - b;
textBox3.Text =Convert.ToString( c);
at bulid this code i see error Use of unassigned local variable'a' and 'b' how can i do
at bulid this code i see error Use of unassigned local variable'a' and 'b'
Yes, you would do. They're not definitely assigned, because your while loop may not execute.
What would you expect the result to be if there are no rows? The answer to that question will determine what you should do. (Also, if there's more than one row, only the last row will contribute to the result - is that deliberate?)
For example, you could just give them values to start with:
double a = 0, b = 0, c;
That will give you a result of 0 if there are no rows. If that's what you want...
(I'd declare the variables as late as you can, mind you.)
Additionally, please use parameterized SQL. Your current code is vulnerable to SQL injection attacks. Oh, and use using statements to make sure you close your command and exception appropriately.
You need to set a and b because maybe the while loop won't execute even one iteration when there is no data in dr.
double a = 0, b = 0, c;

Categories