Set MIN value in a column in Teradata - sql

I need to set the minium value in all the column by the elements in the group by. The problem for the table is the column lastupdate,some values have '0001-01-01', so when I apply MIN() it doesn't give me a correct value.
I trying with this code, but doesn't work. I want to have the MIN value by period and coddoc in all the column.
SELECT
period,
coddoc,
(
CASE WHEN MIN(lastupdate)='0001-01-01'
THEN MIN(lastupdate)
ELSE MIN(lastupdate)
END
) as lastupdate
FROM table
GROUP BY period, coddoc;
Thanks for the help.

Just take advantage of the fact that MIN() ignores NULL values:
SELECT
period,
coddoc,
MIN(CASE WHEN lastupdate = '0001-01-01' THEN NULL ELSE lastupdate END) as lastupdate
FROM table
GROUP BY period, coddoc;
NB : as commented by #dnoeth, the CASE expression can be shortened as :
NULLIF(lastupdate, '0001-01-01')

Why not just filter in the where clause?
SELECT period, coddoc, MIN(lastupdate) as lastupdate
FROM table
WHERE lastupdate > '0001-01-01'
GROUP BY period, coddoc;

Related

Running difference month over month

I have a sample data, i want to get the Difference in month over month data 'Lag' column for only row B
If there always is just one row per month and id, then just use lag(). You can wrap this in a case expression so it only applies to id 'B'.
select
id,
date,
data,
case when id = 'B'
then data - lag(data) over(partition by id order by date)
end lag_diff
from mytable

SQL - Order by Max() on Alias

I gather that I cannot get the MAX() on some alias that I have in the select statement in sql queries?
Example:
Select
CASE WHEN CompletionDate IS NOT NULL THEN DATEDIFF(d, CreatedDate, CompletionDate) ELSE NULL END AS DaysLong
from CombinedMastervw
WHERE CreatedDate Between '03/01/2019 23:59:59.991' AND '04/01/2019 23:59:59.991'
ORDER BY MAX(dayslong)
Thus my question is on MAX(dayslong), do I have to end up doing a Max with the same code in the SELECT statement?
You should be able to use the alias.
Try:
ORDER BY dayslong
Max(dayslong) would return the single maximum value in the table you are selecting, so you cannot order by it.
If you want the max() use top (1) and order by:
Select TOP (1) DATEDIFF(day, CreatedDate, CompletionDate) DaysLong
from CombinedMastervw
WHERE CreatedDate >= '2019-03-01' AND
CreatedDate < '2019-04-02'
ORDER BY dayslong DESC;
I changed the date comparisons so they are for full days. If you really want a few seconds before midnight, then you can change back to your version.

Check if input date falls within table of start and end dates

I'd like to run a query to check if an input date falls within any given term dates from a table.
Example table of Term Dates:
<table border="1">
<tr><th>termID</th><th>txtStartDate</th><th>txtFinishDate</th></tr>
<tr><td>37</td><td>2017-09-05 00:00:00</td><td>2017-12-15 23:59:00</td></tr>
<tr><td>38</td><td>2018-01-09 00:00:00</td><td>2018-03-29 23:59:00</td></tr>
<tr><td>39</td><td>2018-04-24 00:00:00</td><td>2018-07-06 23:59:00</td></tr>
<tr><td>40</td><td>2018-09-04 00:00:00</td><td>2018-12-14 23:59:00</td></tr>
<tr><td>41</td><td>2019-01-08 00:00:00</td><td>2019-03-29 23:59:00</td></tr>
<tr><td>42</td><td>2019-04-24 00:00:00</td><td>2019-07-05 23:59:00</td></tr></table>
Given an date, let's say today's date, does it fall between any of the rows' start and end date.
Example code approach
date = now()
for (row in rows):
if date between row.txtStartDate and row.txtEndDate:
return "yes"
I can use between logic with given dates but unsure how to apply this to the entire table.
select case when getdate() between '2019-04-24 00:00:00' and '2019-07-05 23:59:00' then 'yes' else 'no' END
Thanks
Try to use WHERE operator:
SELECT *
FROM YourTable yt
WHERE GETDATE() BETWEEN yt.txtStartDate AND yt.txtEndDate
You need to reference the table's columns instead of hard-coding the values. You do this using the table's alias and the proper column name.
DECLARE #InputDate DATE = '2019-01-05'
SELECT
T.*
FROM
YourTable AS T
WHERE
#InputDate BETWEEN T.txtStartDate AND T.txtEndDate
Using a WHERE clause will filter the rows from the table and only display the ones in which the condition is true. If you move your condition as an expression of a new column (in the SELECT column list) then it will display all rows with this new expression:
DECLARE #InputDate DATE = '2019-01-05'
SELECT
T.*,
IsInputDateBetweenDates = CASE
WHEN #InputDate BETWEEN T.StartDate AND T.EndDate THEN 'Yes'
ELSE 'No' END
FROM
YourTable AS T
You can try with IF EXISTS also as shown below.
If Exists (Select 1 from YourTable where GETDATE() between txtStartDate AND txtEndDate)
Begin
--Your if logic
end
else
begin
--Your else logic
end

Where clause inside an over clause in postgres

Is it possible to use the where clause inside an overclause as below ?
SELECT SUM(amount) OVER(partition by prod_name WHERE dateval > dateval_13week)
I cannot use preceding and following inside over clause as my dates are not in the order.
All I need to fetch is the records that are less than 13week date value of the current record.
EDIT :
sum(CASE WHEN dateval >= dateval_13week and dateval <=current_row_dateval then amount else 0 end) over (partition by prod_name order by week_end desc)
Just to elaborate, earlier I was partitioning the records with the below query when I had all my dates in a sequence. Now I have the dates in random order and there are some missing dates.
sum(amount) over
(partition by prod_name order by prod_name,week_end desc rows between 0 preceding and 12 following)
Adding to #D Stanley answer you can use FILTER clause for aggregate function in Postgre:
SELECT SUM(amount) FILTER (WHERE dateval > dateval_13week)
OVER(partition by prod_name)
You could simulate the WHERE in your SUM parameter:
SELECT SUM(CASE WHEN dateval > dateval_13week THEN amount ELSE 0 END)
OVER(partition by prod_name)
You cannot filter the rows with the WHERE clause, inside the OVER partition clause.
You can fix the query selecting only the rows that are needed to you, using CASE and performing a sum of the amount where the condition is satisfied.

How do I get a maximium daily value of a numerical field over a year in SQL

How do I get a maximium daily value of a numerical field over a year in MS-SQL
This would query the daily maximum of value over 2008:
select
datepart(dayofyear,datecolumn)
, max(value)
from yourtable
where '2008-01-01' <= datecolumn and datecolumn < '2009-01-01'
group by datepart(dayofyear,datecolumn)
Or the daily maximum over each year:
select
datepart(year,datecolumn),
, datepart(dayofyear,datecolumn)
, max(value)
from yourtable
group by datepart(year,datecolumn), datepart(dayofyear,datecolumn)
Or the day(s) with the highest value in a year:
select
Year = datepart(year,datecolumn),
, DayOfYear = datepart(dayofyear,datecolumn)
, MaxValue = max(MaxValue)
from yourtable
inner join (
select
Year = datepart(year,datecolumn),
, MaxValue = max(value)
from yourtable
group by datepart(year,datecolumn)
) sub on
sub.Year = yourtable.datepart(year,datecolumn)
and sub.MaxValue = yourtable.value
group by
datepart(year,datecolumn),
datepart(dayofyear,datecolumn)
You didn't mention which RDBMS or SQL dialect you're using. The following will work with T-SQL (MS SQL Server). It may require some modifications for other dialects since date functions tend to change a lot between them.
SELECT
DATEPART(dy, my_date),
MAX(my_number)
FROM
My_Table
WHERE
my_date >= '2008-01-01' AND
my_date < '2009-01-01'
GROUP BY
DATEPART(dy, my_date)
The DAY function could be any function or combination of functions which gives you the days in the format that you're looking to get.
Also, if there are days with no rows at all then they will not be returned. If you need those days as well with a NULL or the highest value from the previous day then the query would need to be altered a bit.
Something like
SELECT dateadd(dd,0, datediff(dd,0,datetime)) as day, MAX(value)
FROM table GROUP BY dateadd(dd,0, datediff(dd,0,datetime)) WHERE
datetime < '2009-01-01' AND datetime > '2007-12-31'
Assuming datetime is your date column, dateadd(dd,0, datediff(dd,0,datetime)) will extract only the date part, and then you can group by that value to get a maximum daily value. There might be a prettier way to get only the date part though.
You can also use the between construct to avoid the less than and greater than.
Group on the date, use the max delegate to get the highest value for each date, sort on the value, and get the first record.
Example:
select top 1 theDate, max(theValue)
from TheTable
group by theDate
order by max(theValue) desc
(The date field needs to only contain a date for this grouping to work, i.e. the time component has to be zero.)
If you need to limit the query for a specific year, use a starting and ending date in a where claues:
select top 1 theDate, max(theValue)
from TheTable
where theDate between '2008-01-01' and '2008-12-13'
group by theDate
order by max(theValue) desc