How to get minimum value from the SQL table? - sql

I have a table as below
ID Date
1 Null
1 Null
1 Null
1 02/02/2012
1 02/03/2012
1 02/04/2012
1 02/05/2012
I want to take a min date from the above table, that's result should be Null
I was trying to write
select min(date), Id from Table group by ID
then result is 02/02/2012, but I want Null.
Is there any otherway to pull Null value from the above table except the below method?
select top 1 date, ID from table order by date asc

Assuming that your dbms is SQL-Server.
If you want to group by id but select all fields anyway, you can use a cte with ROW_NUMBER function:
WITH cte AS(
SELECT x.*
, RN=ROW_NUMBER()OVER(Partition By id Order By date)
FROM Table x
)
SELECT * FROM cte
WHERE RN=1
http://sqlfiddle.com/#!3/cc2a4/7

By default the functions MAX and MIN do not count NULL in their evaluation of your data.
Try in this way, should do the trick :
SELECT
CASE WHEN MIN(COALESCE(Date, '19001231')) = '19001231' THEN NULL ELSE MIN(Date) END AS Date,
Id
FROM X
group by ID

I think some of them are given the answer. but the final result working with below query
SELECT CASE WHEN MIN(coalesce(date, '1900-01-01')) = '1900-01-01' THEN NULL ELSE MIN(date) END AS Date, ID
FROM table
GROUP BY ID

You can also do a simple check for 'NULL'. I didn't return an "ID" in the example since the "ID" seems meaningless in the example schema/query given.
IF (EXISTS(SELECT TOP 1 * FROM x WHERE date IS NULL)) SELECT NULL AS MinDate
ELSE SELECT MIN(date) AS MinDate FROM x;
http://sqlfiddle.com/#!3/d5fca/11

Related

How can I obtain the minimum date for a value that is equal to the maximum date?

I am trying to obtain the minimum start date for a query, in which the value is equal to its maximum date. So far, I'm able to obtain the value in it's maximum date, but I can't seem to obtain the minimum date where that value remains the same.
Here is what I got so far and the query result:
select a.id, a.end_date, a.value
from database1 as a
inner join (
select id, max(end_date) as end_date
from database1
group by id
) as b on a.id = b.id and a.end_date = b.end_date
where value is not null
order by id, end_date
This result obtains the most recent record, but I'm looking to obtain the most minimum end date record where the value remains the same as the most recent.
In the following sample table, this is the record I'd like to obtain the record from the row where id = 3, as it has the minimum end date in which the value remains the same:
id
end_date
value
1
02/12/22
5
2
02/13/22
5
3
02/14/22
4
4
02/15/22
4
Another option that just approaches the problem somewhat as described for the sample data as shown - Get the value of the maximum date and then the minimum id row that has that value:
select top(1) t.*
from (
select top(1) Max(end_date)d, [value]
from t
group by [value]
order by d desc
)d
join t on t.[value] = d.[value]
order by t.id;
DB<>Fiddle
I'm most likely overthinking this as a Gaps & Island problem, but you can do:
select min(end_date) as first_date
from (
select *, sum(inc) over (order by end_date desc) as grp
from (
select *,
case when value <> lag(value) over (order by end_date desc) then 1 else 0 end as inc
from t
) x
) y
where grp = 0
Result:
first_date
----------
2022-02-14
See running example at SQL Fiddle.
with data as (
select *,
row_number() over (partition by value) as rn,
last_value(value) over (order by end_date) as lv
from T
)
select * from data
where value = lv and rn = 1
This isn't looking strictly for streaks of consecutive days. Any date that happened to have the same value as on final date would be in contention.

SQL Order by date, then change the value of id with update function

This my first time when I use SQL and I need your help. I have got a table like this:
ID
date
1
01.02.2021
2
03.02.2021
3
04.02.2021
4
02.02.2021
And I can order it by date, then I have got this:
ID
date
1
01.02.2021
4
02.02.2021
2
03.02.2021
3
04.02.2021
I have done this with function UPDATE and ORDER BY. There is a question now. How to order by date, and change the value of ID with update function to get the result like this:
ID
date
1
01.02.2021
2
02.02.2021
3
03.02.2021
4
04.02.2021
Is there any quick method to sort by date and leave the order of ID? I want to help my friend with that but I have never been working with SQL. Sorry for my english.
Try following code
UPDATE table t
SET t.id = t1.NEW_ID
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [Date]) AS New_ID
FROM TABLE
) t1
Please try this,
with my_cte as (
select id, date
, row_number() over(order by date asc) rn
from test
)
update test set id =
(select min(rn) from my_cte
where test.id = my_cte.id and test.date=my_cte.date);

SQL MIN DATE >= 2017-01

I got table with columns [TagTime], [TagValue], [id]. Values in this table comming every 15 min, so there is multiple values with the same id's.
I want select (tagtime,tagvalue,id), that will return only first value in january 2017 for all the id's.
I tried with select top 1, then with group by, distinct... but it doesnt work. Have you some suggestions?
Try this (I assumed you are using MSSQL)
SELECT TOP 1 *
FROM [tbl1]
WHERE DATEPART(MONTH,TagTime) = '01' AND DATEPART(YEAR,TagTime) = '2017'
ORDER BY TagTime DESC
You can go this way
select id, tagvalue, tagtime
from
(select id, tagvalue, tagtime,
row_number() over (partition by id order by tagtime) [RowNum]
from YourTable
where DATEPART(year, tagtime) = 2017) src
where src.[RowNum] = 1
So, you having row number for each ID, ordered by tagtime, and then selecting just first of every ID

How to get next minimum date that is not within 30 days and use as reference point in SQL?

I have a subset of records that look like this:
ID DATE
A 2015-09-01
A 2015-10-03
A 2015-10-10
B 2015-09-01
B 2015-09-10
B 2015-10-03
...
For each ID the first minimum date is the first index record. Now I need to exclude cases within 30 days of the index record, and any record with a date greater than 30 days becomes another index record.
For example, for ID A, 2015-09-01 and 2015-10-03 are both index records and would be retained since they are more than 30 days apart. 2015-10-10 would be dropped because it's within 30 days of the 2nd index case.
For ID B, 2015-09-10 would be dropped and would NOT be an index case because it's within 30 days of the 1st index record. 2015-10-03 would be retained because it's greater than 30 days of the 1st index record and would be considered the 2nd index case.
The output should look like this:
ID DATE
A 2015-09-01
A 2015-10-03
B 2015-09-01
B 2015-10-03
How do I do this in SQL server 2012? There's no limit to how many dates an ID can have, could be just 1 to as many as 5 or more. I'm fairly basic with SQL so any help would be greatly appreciated.
working like in your example, #test is your table with data:
;with cte1
as
(
select
ID, Date,
row_number()over(partition by ID order by Date) groupID
from #test
),
cte2
as
(
select ID, Date, Date as DateTmp, groupID, 1 as getRow from cte1 where groupID=1
union all
select
c1.ID,
c1.Date,
case when datediff(Day, c2.DateTmp, c1.Date) > 30 then c1.Date else c2.DateTmp end as DateTmp,
c1.groupID,
case when datediff(Day, c2.DateTmp, c1.Date) > 30 then 1 else 0 end as getRow
from cte1 c1
inner join cte2 c2 on c2.groupID+1=c1.groupID and c2.ID=c1.ID
)
select ID, Date from cte2 where getRow=1 order by ID, Date
select * from
(
select ID,DATE_, case when DATE_DIFF is null then 1 when date_diff>30 then 1 else 0 end comparison from
(
select ID, DATE_ ,DATE_-LAG(DATE_, 1) OVER (PARTITION BY ID ORDER BY DATE_) date_diff from trial
)
)
where comparison=1 order by ID,DATE_;
Tried in Oracle Database. Similar funtions exist in SQL Server too.
I am grouping by Id column, and based on DATE field, am comparing the date in current field with its previous field. The very first row of a given user id would return null, and first field is required in our output as first index. For all other fields, we return 1 when the date difference with respect to previous field is greater than 30.
Lag function in transact sql
Case function in transact sql
Your logic explained in question is wrong,at one place ,you have said take the first index record and in next place you considered immediate record..
This works for immediate records:
with cte
as
(
select *, ROW_NUMBER() over (partition by id order by datee) as rownum
from #test
)
select *,datediff(day,beforedate,datee)
from cte t1
cross apply
(Select isnull(max(Datee),t1.datee) as beforedate from cte t2 where t1.id =t2.id and t2.rownum<t1.rownum) b
where datediff(day,beforedate,datee)= 0 or datediff(day,beforedate,datee)>=30
This works for constant base record:
select *,datediff(day,basedate,datee) from #test t1
cross apply
(select min(Datee) as basedate from #test t2 where t1.id=t2.id)b
where datediff(day,basedate,datee)>=30 or datediff(day,basedate,datee)=0
Try this solution.
Sample demo
with diffs as (
select t1.id,t1.dt strtdt,t2.dt enddt,datediff(dd,t1.dt,t2.dt) daysdiff
from t t1
join t t2 on t1.id=t2.id and t1.dt<t2.dt
)
, y as (
select id,strtdt,enddt
from (
select id,strtdt,enddt,row_number() over(partition by id,strtdt order by daysdiff) as rn
from diffs
where daysdiff > 30
) x
where rn=1
)
,z as (
select *,coalesce(lag(enddt) over(partition by id order by strtdt),strtdt) prevend
from y)
select id,strtdt from z where strtdt=prevend
union
select id,enddt from z where strtdt=prevend

group rows in plain sql

I have a Table with columns Date and Number, like so:
date Number
1-1-2012 1
1-2-2012 1
1-3-2012 2
1-4-2012 1
I want to make a sql query that groups the rows with the same Number and take the minimum date. The grouping only may occur when the value iof Number is the same as previous / next row. So the rsult is
date Number
1-1-2012 1
1-3-2012 2
1-4-2012 1
try this:
WITH CTE AS(
SELECT * ,ROW_NUMBER() OVER (ORDER BY [DATE] ) -
ROW_NUMBER() OVER (PARTITION BY NUMBER ORDER BY [DATE] ) AS ROW_NUM
FROM TABLE1)
SELECT NUMBER,MIN(DATE) AS DATE
FROM CTE
GROUP BY ROW_NUM,NUMBER
ORDER BY DATE
SQL fiddle demo
SELECT Number, MIN(date)
FROM table
GROUP BY Number
ORDER BY Number
since you requirement is a bit more specific, how about this? I have not checked it myself, but something that might work, considering you requirement..
SELECT date, Number FROM (
SELECT Number,
(SELECT MIN(date) FROM #table t2 WHERE t1.date <> t2.date AND t1.Number = t2.Number) AS date
FROM table t1
) AS a
GROUP BY number, date