Checking SQL MAX() Function returning null - sql-server

My problem is if my table is empty or the column on which I am using max function does not have the value I have specified, then why is sqlDataReader.hasRows TRUE?
It is giving a null record...how do I solve this problem??
Thanks in advance.

An aggregate function like MAX() will always return one row per group. In your case, your group is the whole table. Therefore you get a one row resultset with the MAX value. Since you don't have data in your table, the MAX value is undefined, therefore NULL.
For better understanding try to replace MAX with COUNT. This will also return one row but with value 0. I think this is more intuitive and will help you better to understand what is happening.

Make your query into a derived table and filter out null values in the main query.
select T.MaxValue
from (
-- Your query goes here
select max(Value) as MaxValue
from YourTable
where SomeCol > 10
) as T
where T.MaxValue is not null

Or, use the HAVING clause because HAVING can be used with aggregate functions:
select max(Value) from YourTable where SomeCol > 10
HAVING max(Value) is not null

you can use:
select top(select COUNT(*) from tbl) max(field) from tbl

Related

Row number for for same value

The result of my SQL Server query returns 3 columns.
Select Id, InItemId, Qty
from Mytable
order by InItemId
I need to add a column, call it row, that starts from 1 and will increase by 1, based on the initemid column with same value.
So the result should be:
Thank you !
Use row_number():
select row_number() over (partition by initemid order by initemid) as row,
t.*
from t;
Note: There is no ordering within a given value of initemid. SQL tables represent unordered sets and there is no obvious column to use for ordering.

Snowflake: Unsupported subquery for DISTINCT - Column order matters?

I have two related tables (unnecessary columns not listed):
LOCATION
VENUE_ID - NUMBER(38,0)
VISIT
ID - NUMBER(38,0)
VENUE_ID - NUMBER(38,0)
DEVICE_ID - VARCHAR(16777216)
The tables are related such that visits are associated with a location via VENUE_ID.
I'm attempting to get the count of unique device ids by location, so I wrote the following query:
SELECT "d"."VENUE_ID"
, (
SELECT COUNT(*)
FROM (
SELECT DISTINCT "f0"."DEVICE_ID"
FROM "MAIN"."VISIT" AS "f0"
WHERE "d"."VENUE_ID" = "f0"."VENUE_ID"
) AS "t")
FROM "MAIN"."LOCATION" AS "d"
Unfortunately, this query resulted in the cryptic error SQL compilation error: Unsupported subquery type cannot be evaluated.
Through a bit of experimentation, I've found that I can get the query to return without error, but only if I add an additional (useless) subquery prior to the existing one in the SELECT:
SELECT "d"."VENUE_ID"
-- New Useless Subquery
, (
SELECT COUNT(*)
FROM "MAIN"."VISIT" AS "f"
WHERE "d"."VENUE_ID" = "f"."VENUE_ID")
--
, (
SELECT COUNT(*)
FROM (
SELECT DISTINCT "f0"."DEVICE_ID"
FROM "MAIN"."VISIT" AS "f0"
WHERE "d"."VENUE_ID" = "f0"."VENUE_ID"
) AS "t")
FROM "MAIN"."LOCATION" AS "d"
If I move the new subquery to anywhere in the select after the distinct subquery, the error returns. I've reviewed the documentation on subqueries in Snowflake and either I am not understanding how that applies to my query here or I'm facing undocumented behavior. Anyone have any idea what's going on here?
I think you're making this more complex than this needs to be. Below should be all you need:
SELECT l.venue_id
, count(distinct v.device_id)
FROM location l
LEFT JOIN visit v
on l.venue_id = v.venue_id
GROUP BY l.venue_id
The answer is a little cryptic, but what happens is this:
You are asking for ONE value and you need to guarantee that only ONE value is returned by your subquery. A distinct clause cannot guarantee that. In some databases that will work as long as the data returns one row, but the moment you get two rows then the database will throw an error.
Snowflake is strict on its subquery analysis. So you need to use a subquery that is guarantee to return always one value, for example select sum(..), select count(..)

Create conditional for COUNT

Forgive me if this has been asked but I have been unable to find a solution for this. I'm using the COUNT function, and would like for all returned values greater than 5 to return as ">5".
It seems that the HAVING clause is the way to go, but I don't know how to make it conditional.
Thanks in advance.
SELECT DISTINCT
Column A
COUNT(*) AS VISITS
FROM TABLE A
GROUP BY
Column A
ORDER BY
Column A
you can use case statement to return the correct label,
SELECT ColumnaA, case when count(*) > 5 then '>5' else cast(count(*) as varchar(4)) end as visits
from tableA
group by ColumnA
order by ColumnA

How ROW_NUMBER used with insertions?

I've multipe uniond statements in MSSQL Server that is very hard to find a unique column among the result.
I need to have a unique value per each row, so I've used ROW_NUMBER() function.
This result set is being copied to other place (actually a SOLR index).
In the next time I will run the same query, I need to pick only the newly added rows.
So, I need to confirm that, the newly added rows will be numbered afterward the last row_number value of the last time.
In other words, Is the ROW_NUMBER functions orders the results with the insertion order - suppose I don't adding any ORDER BY clause?
If no, (as I think), Is there any alternatives?
Thanks.
Without seeing the sql I can only give the general answer that MS Sql does not guarantee the order of select statements without an order clause so that would mean that the row_number may not be the insertion order.
I guess you can do something like this..
;WITH
cte
AS
(
SELECT * , rn = ROW_NUMBER() OVER (ORDER BY SomeColumn)
FROM
(
/* Your Union Queries here*/
)q
)
INSERT INTO Destination_Table
SELECT * FROM
CTE LEFT JOIN Destination_Table
ON CTE.Refrencing_Column = Destination_Table.Refrencing_Column
WHERE Destination_Table.Refrencing_Column IS NULL
I would suggest you consider 'timestamping' the row with the time it was inserted. Or adding an identity column to the table.
But what it sounds like you want to do is get current max id and then add the row_number to it.
Select col1, col2, mid + row_number() over(order by smt) id
From (
Select col1, col2, (select max(id) from tbl) mid
From query
) t

How do I make this SQL query work (computed column with nested query)?

I want to have a computed column that is true if the field asofdate is equal to the maximum asofdate in the table, otherwise false. I tried the following but I am getting a syntax error. What is the right way to do this?
select
case asofdate
when select max(asofdate) from sometable then 1
else 0
end
from sometable
Alternatively, is it possible to have a computed column along the lines of
case asofdate
when END OF PREVIOUS MONTH then 1
else 0
end
From the MSDN article
A computed column is computed from an
expression that can use other columns
in the same table. The expression can
be a noncomputed column name,
constant, function, and any
combination of these connected by one
or more operators. The expression cannot be a subquery.
So no you can't make a computed column that way.
You cannot do it in an computed column, since the computed column can be only computed from the values of other columns in the same record.
You can do it in a view, instead:
CREATE VIEW
v_with_last
AS
SELECT *, CASE asofdate WHEN MAX(asofdate) OVER () THEN 1 ELSE 0 END AS the_last
FROM sometable
Unfortunately, you cannot index this view.
In MS Sql Server
SELECT case asofdate
WHEN (SELECT MAX(asofdate) FROM sometable) THEN 1
ELSE 0 END
FROM sometable
EDIT based on comments
To get the end of the previous month -
SELECT DATEADD(dd,-(DAY(asofdate)),asofdate)
I dont know if this would work, but you could create a computed column with formula as 'MAX(asofdate)', create an index on that column and then create a view that just compares the computed column with asofdate. Maybe not the best possible solution, but might be slightly better than just doing a subquery.
so the maximum value of asofdate is stored in a table called sometable right? In that case you dont have to check it using a subquery for every record. You can stored it in a variable and then check the current asofdate towards that.
declare #maxAsOfDate datetime;
Select #maxAsOfDate = max(asofdate) from sometable;
Select case when asofdate >= #maxAsOfDate then 1 else 0 end from sometable
Cheers!

Resources