how to compare SQL dates with null - sql

I want to count the number of rows having date is null.i tried following
SELECT R.COUNTRY_CD,COUNT(R.EFFECTIVE_END_DT) AS d_null
FROM REIMBURSEMENT R
GROUP BY R.COUNTRY_CD,R.EFFECTIVE_END_DT
HAVING R.COUNTRY_CD = #COUNTRY_CD AND R.EFFECTIVE_END_DT IS NULL
but it's giving d_null as 0...
how can i compare a date for NULL

COUNT only counts non-NULL entries.
Try COUNT(*) or COUNT(1) instead of COUNT(R.EFFECTIVE_END_DT).
Since you provide a Country_CD as parameter, and you only want NULL dates, you can probably simplify your query to:
SELECT R.Country_CD, COUNT(*) AS d_null
FROM Reimbursement R
WHERE R.Country_CD = #Country_CD AND R.Effective_End_DT IS NULL

Try this
SELECT R.COUNTRY_CD,COUNT(R.EFFECTIVE_END_DT) AS d_null
FROM REIMBURSEMENT R
GROUP BY R.COUNTRY_CD,R.EFFECTIVE_END_DT
HAVING R.COUNTRY_CD = #COUNTRY_CD AND DATE_FORMAT(R.EFFECTIVE_END_DT,"%y") IS NULL

Related

PostgreSQL, NOT IN clause

I want to calculate DAU and exclude user that we don't consider "real" (employees, beta testers etc).
It worked fine previously when I wrote the filtering in the query:
SELECT
count(distinct user_id) AS daily,
e.event_timestamp::DATE AS date
FROM
"public"."events" AS e
WHERE
user_id IN (SELECT
distinct id
from
"user"."user"
WHERE
username IS NOT NULL AND position IS NOT NULL )
GROUP BY date
When I try changing it to below, which should give more or less the same count (basically instead of defining the 4000 "real users" I define the 1000 "non-users" I want to exclude). However, this gives me way higher counts. It's like the distinct statement isn't working.
I added the NOT NULL to the subquery but doesn't change the result. Is there something with the NOT IN + subquery that works in another way than the IN clause?
SELECT
count(distinct e.user_id) AS daily,
e.event_timestamp::DATE AS date
FROM
"public"."events" AS e
WHERE
e.user_id NOT IN (SELECT distinct id FROM "public"."non_users" WHERE id IS NOT NULL)
GROUP BY
date
ORDER BY
date
Yes. If any of the values in the subquery are NULL, then NOT IN returns no rows For this reason, I strongly recommend that you always use NOT EXISTS -- it behaves as expected.
You seem to know this, because you are using a NULL comparison in the WHERE. So, the difference is probably due to the other condition. So, include it as well:
SELECT count(distinct e.user_id) AS daily,
e.event_timestamp::DATE AS date
FROM "public"."events" e
WHERE NOT EXISTS (SELECT 1
FROM "public"."non_users" nu
WHERE e.user_id = nu.id AND
nu.position IS NOT NULL
)
GROUP BY date
ORDER BY date;

Null query in postgreSQL

I am trying to find the number of rows in a table with a particular column value = NULL in PostgreSQL. This is my query:
SELECT count(*)
FROM database.table
WHERE place_id = 3 AND user = (NULL);
And I get the count as 0. But there a pretty number of rows matching the query. What am I doing wrong here?
You should use IS NULL:
Select count (*) from database.table where place_id = 3 and user IS NULL;
Do not write expression = NULL because NULL is not "equal to" NULL. (The null value represents an unknown value, and it is not known whether two unknown values are equal.) This behavior conforms to the SQL standard.
If the value NULL comes from a variable, you can use IS DISTINCT FROM or IS NOT DISTINCT FROM which can compare NULL values:
SELECT COUNT(*) from database.table
WHERE place_id = 3 and user IS NOT DISTINCT FROM NULL
This query will also work for other values, especially parameters. The query
SELECT COUNT(*) from database.table
WHERE place_id = 3 and user IS NOT DISTINCT FROM $1
will work for $1 = 'Tom' and even $1 = NULL.

Oracle SQL Developer - Count function

This is the output of a select * from table1, I have a doubt with count function... I want to count that NULL, in order to do that the proper option is to do this:
select count(*) from table1 where fecha_devolucion is null --> This gives me the proper answer counting 1 however if i do:
select count(fecha_devolucion)
from table1
where fecha_devolucion is null --> this returns 0, why? Isn't the same syntax?
What's the difference between choosing a specific field and * from a table?
From the documentation (http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions032.htm):
If you specify expr, then COUNT returns the number of rows where expr
is not null. ...
If you specify the asterisk (*), then this function returns all rows...
In other words, COUNT(fecha_devolucion) counts non-NULL values of that column. COUNT(*) counts the total number of rows, regardless of the values.
This is the another way how you can get the count :
SELECT SUM(NVL(fecha_devolucion,1)) FROM table1 WHERE fecha_devolucion IS NULL;
Let's compare the two queries:
select count(*)
from table1
where fecha_devolucion is null;
select count(fecha_devolucion)
from table1
where fecha_devolucion is null;
I think you misunderstand the count() function. This function counts the number of non-NULL values in its argument list. With a constant or *, it counts all rows.
So, the first counts all the matching rows. The second counts all the non-NULL values of fecha_devolucion. But there are no such values because of the where clause.
By the way, you can also do:
select sum(case fecha_devolucion is null then 1 else 0 end) as Nullfecha_devolucion
from table1;

SQL: Updating a column based on subquery results

I have a T-SQL table that contains the following columns: Date, StationCode, HDepth, and MaxDepth. Each row in the MaxDepth column is set to 0 by default. What I am trying to do is find the maximum HDepth by Date and StationCode, and update the MaxDepth to a column on these rows. I have written a SELECT statement to find where the maximums occur and it is:
SELECT StationCode, [Date], MAX(HDepth) AS Maximum FROM dbo.[DepthTable] GROUP BY [Date], StationCode
How could I put this query into an Update statement to set the MaxDepth to 1 on the rows that are returned by this query?
You might try something like this:
UPDATE a
SET MaxDepth = 1
FROM dbo.[DepthTable] AS a
JOIN (
-- Your original query
SELECT StationCode, [Date], MAX(HDepth) AS Maximum
FROM dbo.[DepthTable]
GROUP BY [Date], StationCode
) AS b ON a.StationCode = b.StationCode
AND a.[DATE] = b.[DATE]
AND a.HDepth = b.Maximum -- Here we get only the max rows
However, if a column is simply based upon other columns, then you might think about putting this logic into a view (to avoid update anomalies). The select for such a view might look like:
SELECT a.[Date], a.StationCode, a.HDepth,
CASE WHEN b.Maximum IS NULL THEN 0 ELSE 1 END AS MaxDepth
FROM dbo.[DepthTable] AS a
LEFT JOIN (
-- Your original query
SELECT StationCode, [Date], MAX(HDepth) AS Maximum
FROM dbo.[DepthTable]
GROUP BY [Date], StationCode
) AS b ON a.StationCode = b.StationCode
AND a.[DATE] = b.[DATE]
AND a.HDepth = b.Maximum -- Here we get only the max rows

How return a count(*) of 0 instead of NULL

I have this bit of code:
SELECT Project, Financial_Year, COUNT(*) AS HighRiskCount
INTO #HighRisk
FROM #TempRisk1
WHERE Risk_1 = 3
GROUP BY Project, Financial_Year
where it's not returning any rows when the count is zero. How do I make these rows appear with the HighRiskCount set as 0?
You can't select the values from the table when the row count is 0. Where would it get the values for the nonexistent rows?
To do this, you'll have to have another table that defines your list of valid Project and Financial_Year values. You'll then select from this table, perform a left join on your existing table, then do the grouping.
Something like this:
SELECT l.Project, l.Financial_Year, COUNT(t.Project) AS HighRiskCount
INTO #HighRisk
FROM MasterRiskList l
left join #TempRisk1 t on t.Project = l.Project and t.Financial_Year = l.Financial_Year
WHERE t.Risk_1 = 3
GROUP BY l.Project, l.Financial_Year
Wrap your SELECT Query in an ISNULL:
SELECT ISNULL((SELECT Project, Financial_Year, COUNT(*) AS hrc
INTO #HighRisk
FROM #TempRisk1
WHERE Risk_1 = 3
GROUP BY Project, Financial_Year),0) AS HighRiskCount
If your SELECT returns a number, it will pass through. If it returns NULL, the 0 will pass through.
Assuming you have your 'Project' and 'Financial_Year' where Risk_1 is different than 3, and those are the ones you intend to include.
SELECT Project, Financial_Year, SUM(CASE WHEN RISK_1 = 3 THEN 1 ELSE 0 END) AS HighRiskCount
INTO #HighRisk
FROM #TempRisk1
GROUP BY Project, Financial_Year
Notice i removed the where part.
By the way, your current query is not returning null, it is returning no rows.
Use:
SELECT x.Project, x.financial_Year,
COUNT(y.*) AS HighRiskCount
INTO #HighRisk
FROM (SELECT DISTINCT t.project, t.financial_year
FROM #TempRisk1
WHERE t.Risk_1 = 3) x
LEFT JOIN #TempRisk1 y ON y.project = x.project
AND y.financial_year = x.financial_year
GROUP BY x.Project, x.Financial_Year
The only way to get zero counts is to use an OUTER join against a list of the distinct values you want to see zero counts for.
SQL generally has a problem returning the values that aren't in a table. To accomplish this (without a stored procedure, in any event), you'll need another table that contains the missing values.
Assuming you want one row per project / financial year combination, you'll need a table that contains each valid Project, Finanical_Year combination:
SELECT HR.Project, HR.Financial_Year, COUNT(HR.Risk_1) AS HighRiskCount
INTO #HighRisk HR RIGHT OUTER JOIN ProjectYears PY
ON HR.Project = PY.Project AND HR.Financial_Year = PY.Financial_Year
FROM #TempRisk1
WHERE Risk_1 = 3
GROUP BY HR.Project, HR.Financial_Year
Note that we're taking advantage of the fact that COUNT() will only count non-NULL values to get a 0 COUNT result for those result set records that are made up only of data from the new ProjectYears table.
Alternatively, you might only one 0 count record to be returned per project (or maybe one per financial_year). You would modify the above solution so that the JOINed table has only that one column.
Little longer, but what about this as a solution?
IF EXISTS (
SELECT *
FROM #TempRisk1
WHERE Risk_1 = 3
)
BEGIN
SELECT Project, Financial_Year, COUNT(*) AS HighRiskCount
INTO #HighRisk
FROM #TempRisk1
WHERE Risk_1 = 3
GROUP BY Project, Financial_Year
END
ELSE
BEGIN
INSERT INTO #HighRisk
SELECT 'Project', 'Financial_Year', 0
END
MSDN - ISNULL function
SELECT Project, Financial_Year, ISNULL(COUNT(*), 0) AS HighRiskCount
INTO #HighRisk
FROM #TempRisk1
WHERE Risk_1 = 3
GROUP BY Project, Financial_Year