How to substitute and display "0" for NULL when Query fails - sql

I am working in MS WebMatrix using razor.
The issue I am having is that if one of my queries resolves to an error (dividing by 0, for instance) the whole page fails. I want the query to output "0" for this.
Code:
var itot = db.QueryValue("SELECT SUM(SUBTOTAL) from dbo.DR_TRANS where TRANSDATE = 41195 and SUBTOTAL >0");
var ctot = db.QueryValue("SELECT SUM(SUBTOTAL) from dbo.DR_TRANS where TRANSDATE = 41195 and TRANSTYPE = 1 and SUBTOTAL <0");
var nett = itot + ctot;
So, if either itot or ctot renders Null or error because there is no entries for the selected date, how do I get it to treat error as "0" so the math still works? In this example, itot is total invoices raised today, ctot is total credits raised today.
If there are no invoices yet, or if there are no credits raised yet, my code throws an error and shuts the page down. I want it to display 0 if there's none of either, and the value of itot if theres no ctot.
What am I doing wrong? it works fine the moment there's some of each, but I want it to work before that, because there's other code on the page for displaying other query results.
I'm very new to coding queries, so there will be a basic answer I have missed in my online searching!

Wrapping the aggregate function with COALESCE should return 0 rather than NULL:
SELECT COALESCE(SUM(SUBTOTAL), 0)
FROM dbo.DR_TRANS
WHERE TRANSDATE = 41195
AND SUBTOTAL >0
ie a function that returns the first parameter if it is not null, and the second parameter if the first is NULL. I don't know what function to use with webmatrix, but COALESCE is pretty standard. In Oracle, you could use NVL. ISNULL is another such function.

#Glenn offers a perfectly fine solution using SQL. However, you might prefer to understand how to deal with nulls in c#. The null-coalescing operator ?? which is a mouthful, says if something is not null, use it, and if it's null, use what's after the ??. An example is way easier to understand than what I just wrote. The last line of your code would look like:
var nett = itot ?? 0 + ctot ?? 0;
Basically the ?? 0 says if it's null, treat it as a zero, otherwise use the value itself.
I prefer to do as much as possible in c#, and keep my SQL as simple as possible. But I recognize that's more of a personal preference.
In general, there will be cases where you have to deal with nulls being returned by your SQL, perhaps a field where null means the user hasn't entered anything, and a zero means the user did enter a zero. In those case, you can test for null in your c#, like
if ( itot == null )
{
// do appropriate null stuff
itot = 0;
}
else
{
// do non null stuff
// nothing needed in this case
}

Related

Struggling with simple boolean WHERE clause

Tired brain - perhaps you can help.
My table has two bit fields:
1) TestedByPCL and
2) TestedBySPC.
Both may = 1.
The user interface has two corresponding check boxes. In the code I convert the checks to int.
int TestedBySPC = SearchSPC ? 1 : 0;
int TestedByPCL = SearchPCL ? 1 : 0;
My WHERE clause looks something like this:
WHERE TestedByPCL = {TestedByPCL.ToString()} AND TestedBySPC = {TestedBySPC.ToString()}
The problem is when only one checkbox is selected I want to return rows having the corresponding field set to 1 or both fields set to 1.
Now when both fields are set to 1 my WHERE clause requires both check boxes to be checked instead of only one.
So, if one checkbox is ticked return records with with that field = 1 , regardless of whether the other field = 1.
Second attempt (I think I've got it now):
WHERE ((TestedByPCL = {chkTestedByPCL.IsChecked} AND TestedBySPC = {chkTestedBySPC.IsChecked})
OR
(TestedByPCL = 1 AND TestedBySPC = 1 AND 1 IN ({chkTestedByPCL.IsChecked}, {chkTestedBySPC.IsChecked})))
Misunderstood the question.
Change the AND to an OR:
WHERE TestedByPCL = {chkTestedByPCL.IsChecked} OR TestedBySPC = {chkTestedBySPC.IsChecked}
Also:
SQL Server does not have a Boolean data type, it's closest option is a bit data type.
The usage of curly brackets suggests using string concatenations to build your where clause. This might not be a big deal when you're handling checkboxes but it's a security risk when handling free text input as it's an open door for SQL injection attacks. Better use parameters whenever you can.

Linq to entities if in select statement

I have this linq query
Dim chiamateAperte = From statoRic In
dbVulcano.StatoRic.Where(Function(s) s.RFStato >= 11 And s.RFStato <= 13 And s.Attuale = 1 And s.RFTecnico = rfTecnico)
From richiesta In
dbVulcano.Richieste.Where(Function(r) r.IDRic = statoRic.RFRic).DefaultIfEmpty()
From cliente In
dbVulcano.Clienti.Where(Function(c) c.IDCliente = richiesta.RFCliente).DefaultIfEmpty()
Select statoRic.ID, statoRic.RFRic, statoRic.RFStato, statoRic.Attuale, richiesta.Descr, cliente.RagSociale, statoRic.DataAss, statoRic.Data, dataf = If(statoRic.DataAss.HasValue, statoRic.DataAss, statoRic.Data), statoRic.OraDalle, statoRic.OraAlle
Order By dataf Descending, statoRic.OraDalle Ascending
It's working fine but I want to add an order condition on "OraDalle" field.
OraDalle it's sort of a time field, but sadly on db it's defined as smallInt (and I cannot change it), so the format is like "800" to say "eight o'clock". This field can be null.
So instead of statoRic.OraDalle I tried this:
orad=if (statoRic.OraDalle.HasValue,statoRic.OraDalle,2359)
And then
Order By dataf Descending, orad Ascending
But it throws an ugly error: cannot cast system nullable 1 to system object of type 'system.nullable'. Only primitive types or enumeration types are supported in this context
Then I tried this:
orad=statoRic.OraDalle.GetValueOrDefault(2359)
But it also throw an error like: linq to entities does not recognize the method 'Int16 GetValueOrDefault(Int16)'
So... how can I achieve what I want? This whole mess is to get a list ordered by time, where null time values are at the bottom (and not on the top, as default). Thank you all!
Instead of if (statoRic.OraDalle.HasValue,statoRic.OraDalle,2359) use if (statoRic.OraDalle,2359)
This is the equivalent of C#´s null-coalescing-operator ??:
statoRic.OraDalle ?? 2359 which was the solution for a similar question.

Using linQ to perform a simple select where

I am using VS2013 with SQL server 2012, VB.net. I am developing a web application.
Let me say before I ask the question that this will probably be extremely simple for this board but I have not been able to find this through googling.
I have an SQL table that holds some data, two columns (settingName (nvarchar) and settingValue (float)). I want to do the following but using LinQ.
SELECT Settingvalue
FROM Settings
WHERE settingName = 'Name1'
I have the following so far in VB.
Dim db As New GMConnectionDataContext
Dim result = From a In db.Settings
Where a.SettingName = "Name1"
Select a.SettingValue
txtEgdon.Text = result
This doesn't work as result is a double but if I add .tostring to result then the output in the text box is the full linq query not the result I am looing for.
I just need to understand this simple query so I can build on it but I just cant get it and any help offered would be great.
This is because your result is an IQueryable and not a single value(even if you expect it to be). This is also why ToString will get you the SQL that will be run against your DB.
You need to get either the First or if you are really sure this would be a single value get Single. The OrDefaults are used in the case that no value is returned so the result will be null.
A Few options:
// You expect 1 to many results and get the first
txtEgdon.Text = result.First().ToString()
// You expect 0 to many results and get the first or null in case of zero results
txtEgdon.Text = result.FirstOrDefault().ToString()
// You expect exactly 1 result and get it (you will get an exception if no results are returned)
txtEgdon.Text = result.Single().ToString()
// You expect exactly 0 or 1 results and get null or the result
txtEgdon.Text = result.SingleOrDefault().ToString()
I would prefer the FirstOrDefault()

Nhibernate query condition within sum

I am trying the following code but nhibernate is throwing the following exception:
Expression type 'NhSumExpression' is not supported by this SelectClauseVisitor.
var data =
(
from a in session.Query<Activity>()
where a.Date.Date >= dateFrom.Date && a.Date.Date <= dateTo.Date
group a by new { Date = a.Date.Date, UserId = a.RegisteredUser.ExternalId } into grp
select new ActivityData()
{
UserID = grp.Key.UserId,
Date = grp.Key.Date,
Bet = grp.Sum(a => a.Amount < 0 ? (a.Amount * -1) : 0),
Won = grp.Sum(a => a.Amount > 0 ? (a.Amount) : 0)
}
).ToArray();
I've been looking around and found this answer
But I am not sure what I should use in place of the Projections.Constant being used in that example, and how I should create a group by clause consisting of multiple fields.
It looks like your grouping over multiple columns is correct.
This issue reported in the NHibernate bug tracker is similar: NH-2865 - "Expression type 'NhSumExpression' is not supported by this SelectClauseVisitor."
Problem is that apart from the less-than-helpful error message, it's not really a bug as such. What happens in NH-2865 is that the Sum expression contains something which NHibernate doesn't know how to convert into SQL, which result in this exception being thrown by a later part of the query processing.
So the question is, what does you sum expression contains that NHibernate cannot convert? The thing that jumps to mind is the use of the ternary operator. I believe the NHibernate LINQ provider has support for the ternary operator, but maybe there is something in this particular combination that is problematic.
However, I think your expressions can be written like this instead:
Bet = grp.Sum(a => Math.Min(a.Amount, 0) * -1), // Or Math.Abs() instead of multiplication.
Won = grp.Sum(a => Math.Max(a.Amount, 0))
If that doesn't work, try to use a real simple expression instead, like the following. If that works, we at least know the grouping itself work as expected.
Won = grp.Sum(a => a.Amount)

Hibernate createSQLQuery and Toad SQL query return different results - parameter problems?

I'm a newbie at Hibernate so excuse me if some of this is glaringly obvious but it's been a very, very long day. I am trying to create and execute a simple query in Hibernate and Toad/Oracle.
The Toad/Oracle sql reads:
select
count(*)
from
fpps_owner.fee_claim_payment_lines l,
fpps_owner.fee_claim_payments p
where
l.fee_claim_payment_id = p.fee_claim_payment_id and
p.claim_index = 87167895
The above returns 10 records, which is correct
The following Java code returns 0 records, which is NOT correct
String sLinesAvailable =
"select count(*) from " +
"fpps_owner.fee_claim_payment_lines l, fpps_owner.fee_claim_payments p " +
"where " +
"l.fee_claim_payment_id = p.fee_claim_payment_id and p.claim_index = :id";
Query qLinesAvailable = em.createNativeQuery(sLinesAvailable);
qLinesAvailable.setParameter("id", "87167895"); // fails
qLinesAvailable.setParameter("id", 87167895); // fails
List<Object> out = (List<Object>) qLinesAvailable.getResultList();
BigDecimal x = (BigDecimal) out.get(0);
Returns 0 records. Using .getSingleResult() also returns 0 records.
What am I missing here?
Any help would be GREATLY appreciated!
If you are not seeing any malformed query errors, it seems like the parameter is not binding correctly.
To debug, I'd print out that SQL statement the line after you set the parameter. This is the only way you can see the SQL after the parameter is set in order to compare it with Toad.
What does your binding file look like? Maybe you have a different name in there for the ID, so it's not able to find it based on the name. Trying binding with the parameter's order value, just as a test.
This might give some ideas: http://www.mkyong.com/hibernate/hibernate-parameter-binding-examples/
Best of luck! We've all been there :)
What happens when you try:
(Number) query.getSingleResult();
Your query isn't returning a list, but rather just a count.
Good luck.