How to filter only a subset of data while maintain existing records as is in a table? - sql

[SQL Novice] I have a table that looks like this:
id date
1 2019-01-01
1 2019-01-02
2 2019-03-01
2 2019-05-01
I want to only filter the id column on 2 where date is between 2019-04-01 and 2019-05-01 without impacting id equals 1.
The new table should look like this:
id date
1 2019-01-01
1 2019-01-02
2 2019-03-01
I tried this:
select * from table1 where id =2 and date between 2019-03-01 and 2019-04-01
And get this data set:
id date
2 2019-03-01

I think you want or:
where id = 1 or
(id = 2 and date between '2019-03-01' and '2019-04-01')

for your desired result need
select * from table1 where [date] >= '2019-01-01' and [date] <= '2019-03-01'

Related

Query to find value in column dependent on a different column in table being the minimum date

I have a dataset that looks like this. I would like to pull a distinct id, the minimum date and value on the minimum date.
id date value
1 01/01/2020 0.5
1 02/01/2020 1
1 03/01/2020 2
2 01/01/2020 3
2 02/01/2020 4
2 03/01/2020 5
This code will pull the id and the minimum date
select Distinct(id), min(nav_date)
from table
group by id
How can I get the value on the minimum date so the output of my query looks like this?
id date value
1 01/01/2020 0.5
2 01/01/2020 3
Use distinct on:
select distinct on (id) t.*
from t
order by id, date;
This can take advantage of an index on (id, date) and is typically the fastest way to do this operation in Postgres.

Change Dates using Lag based on condition

Input Table :
date_1 date_2 ID
2019-01-01 2019-06-30 1
2019-05-01 2019-05-31 1
2019-06-01 2019-07-30 1
2019-01-02 2019-02-28 2
2019-03-01 2019-08-30 2
2019-01-02 2019-02-28 3
2019-02-06 2019-08-30 3
I am working on a complex HIVE problem of dates.
I need to changes dates of date_1 column and date_2 column for same ID.
I want to copy date_2's date to date_1's date in next row based on a condition. And all this I have to do for each ID, i.e. partition By ID.
Note : Data is sorted by ID asc, date_1 asc, date_2 asc.
For example :
Consider 2nd row, date_1 date is '2019-05-01' and now see its previous row for same ID 1 , here date_2 date is '2019-06-30'.
So check IF date_2 value of any row's previous row is greater than current row's value of date_1 , which is true in case of second row of ID 1.
When true then replace date_1 value of second row with date_2 value of previous row.
i.e. change 2019-05-01 to 2019-06-30, otherwise keep it as it is. Same do it for 3rd row and so on.
when considering 3rd row , then look for its previous row 2nd . And same goes for other rows.
Consider 2nd row of ID 2.
Here 2019-02-28is not greater than 2019-03-01 , so keep it as it is.
Expected Output :
date_1 date_2 ID
2019-01-01 2019-06-30 1
2019-06-30 2019-05-31 1
2019-06-01 2019-07-30 1
2019-01-02 2019-02-28 2
2019-03-01 2019-08-30 2
2019-01-02 2019-02-28 3
2019-02-28 2019-08-30 3
I think you want lag() like this
select date_add(lag(date2, 1, date1) over (partition by id order by date1), 1) as date1,
date2,
id
from t;

Query to find rows with nearest date in future

I'm trying to display a result set based on a min date value and today's date but can't seem to make it work. It's essentially a date sensitive price list.
Example Data
ID Title Value ExpireDate
1 Fred 10 2019-03-01
2 Barney 15 2019-03-01
3 Fred2 20 2019-06-01
4 Barney2 25 2019-06-01
5 Fred3 30 2019-07-01
6 Barney3 55 2019-07-01
Required Results:
Display records based on minimum date > GetDate()
3 Fred2 20 2019-06-01
4 Barney2 25 2019-06-01
Any assistance would be great - thank you.
Use where clause to filter all future rows and row_number() to find the first row per group:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Title ORDER BY ExpireDate) AS rn
FROM t
WHERE ExpireDate >= CAST(CURRENT_TIMESTAMP AS DATE)
) AS x
WHERE rn = 1
Based on your revised question, you can simply do this:
SELECT TOP 1 WITH TIES *
FROM t
WHERE ExpireDate >= CAST(CURRENT_TIMESTAMP AS DATE)
ORDER BY ExpireDate

How to replicate rows by generating months in postgres

I have a table with customer details
Table Customer:
CID CNAME
1 Abc
2 Def
3 Ghi
i want to add a month column to this table and replicate all the rows for every month in a select statement. months have to be generate based on current date.
Intended Output
Month CID CNAME
2019-01-01 1 Abc
2019-01-01 2 Def
2019-01-01 3 Ghi
2019-02-01 1 Abc
2019-02-01 2 Def
2019-02-01 3 Ghi
2019-03-01 1 Abc
2019-03-01 2 Def
2019-03-01 3 Ghi
You are looking for generate_series(). I would do this as:
select gs.month, t.*
from t cross join
generate_series('2019-01-01'::date, '2019-03-01'::date, interval '1 month') gs(month)
order by gs.month, t.cid;
to answer my question
SELECT DATE '2019-01-01' + (interval '1' month * generate_series(0,2)) as "month",
company_id,
company_name
FROM
company;
Instead of using a cross join we can do it inline.

Update the list of dates to have the same day

I have this in my table
TempTable
Id Date
1 1-15-2010
2 2-14-2010
3 3-14-2010
4 4-15-2010
i would like to change every record so that they have all same day, that is the 15th
like this
TempTable
Id Date
1 1-15-2010
2 2-15-2010 <--change to 15
3 3-15-2010 <--change to 15
4 4-15-2010
what if i like on the 30th?
the records should be
TempTable
Id Date
1 1-30-2010
2 2-28-2010 <--change to 28 because feb has 28 days only
3 3-30-2010 <--change to 30
4 4-30-2010
thanks
You can play some fun tricks with DATEADD/DATEDIFF:
create table T (
ID int not null,
DT date not null
)
insert into T (ID,DT)
select 1,'20100115' union all
select 2,'20100214' union all
select 3,'20100314' union all
select 4,'20100415'
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100115')
from T
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100130')
from T
Results:
ID
----------- -----------------------
1 2010-01-15 00:00:00.000
2 2010-02-15 00:00:00.000
3 2010-03-15 00:00:00.000
4 2010-04-15 00:00:00.000
ID
----------- -----------------------
1 2010-01-30 00:00:00.000
2 2010-02-28 00:00:00.000
3 2010-03-30 00:00:00.000
4 2010-04-30 00:00:00.000
Basically, in the DATEADD/DATEDIFF, you specify the same component to both (i.e. month). Then, the second date constant (i.e. '20100130') specifies the "offset" you wish to apply from the first date (i.e. '20100101'), which will "overwrite" the portion of the date your not keeping. My usual example is when wishing to remove the time portion from a datetime value:
SELECT DATEADD(day,DATEDIFF(day,'20010101',<date column>),'20100101')
You can also try something like
UPDATE TempTable
SET [Date] = DATEADD(dd,15-day([Date]), DATEDIFF(dd,0,[Date]))
We have a function that calculates the first day of a month, so I just addepted it to calculate the 15 instead...