Last year occurrence of date and month - sql

I am looking to find a way to find the last time the day and year combination has happened.
I have a long list of dates and I want to find out what year the date and month has last occurred.
ie. 01/01 has happened in 2018 so I want 2018 as the output.
31/12 has not happened in 2018 yet, the last time is happened was in 2017, so I want 2017 as the output.
Table 1
(01/01/2015),
(01/01/2016),
(31/12/2015),
(25/07/2004)
Return table 2
(01/01/2015, 01/01/2018),
(01/01/2016, 01/01/2018),
(31/12/2015, 31/12/2017),
(25/07/2004, 25/07/2017)
OR even just return
(01/01/2015, 2018),
(01/01/2016, 2018),
(31/12/2015, 2017),
(25/07/2004, 2017)

Is this what you want?
select t2.*,
(case when month(col) < month(current_date) or
(month(col) < month(current_date) and day(col) <= day(current_date))
then year(current_date)
else 1 + year(current_date)
end)
from table2 t2;
This is using a reasonable set of date/time functions. These can vary by database.

To filter the month and year of a given date to the current date you can use:
SELECT *
FROM YourTable
WHERE month(date) = month(get_some_date()) and year(date) = year(get_somedate())
Here you can replace get_some_date to your function logic.

Related

Find and sort all the data(dates) after a certain date by month/day and not year in SQLite

I wanna order the data in an sqlite3 database by date. (Day and Month to be precise)
I have a table,
the data in the table are in the format YYYY-MM-DD
2003-02-20, 2005-07-16, 2008-11-18, 1998-01-02, 1996-08-27
Here, I wanna find all the data after a certain date(Current date- 'now') and in order.
The data is birthdays, so the order should be just based off of Month and Day and shouldn't care about the year.
For example, the data here is
Feb 20, Jul 16, Nov 18, Jan 1, Aug 27
current day= July 28
I want the output to look like
Aug 27, Nov 18, Jan 1, Feb 20, Jul 16
I've looked through many examples and documentations and tried some methods
SELECT * FROM table WHERE birthdays>date('now')
*birthdays are the column where dates are stored*
This gives all the data after ('now') as an output, but it orders it by year as well. Hence, the output will be none since none of the years are greater than current year. I wanna take the year out of the equation and just order it by Month and Day.
How can I do it?
You don't need a WHERE clause because all rows of the table should be returned.
What you want is a proper ORDER BY clause:
SELECT *
FROM tablename
ORDER BY strftime('%m-%d', birthdays) > strftime('%m-%d', 'now') DESC,
strftime('%m-%d', birthdays);
See the demo.
According to the sample data and the expected output you posted, you want to find all birthdays that will occur this year after the date of today. You may use the strftime function to extract month and day as the following:
Select user_id, DOB
From your_table
Where strftime('%m-%d',DOB) > strftime('%m-%d',date())
Order By strftime('%m-%d',DOB)
See a demo from db-fiddle.
you can select the dates, by taking he day of birth, adding the current year ( or the next one if it is smalerer tan the current date)and then selecting the dates that are bigger than the current date limiting 10
SELECT user_id, DOB
FROM your_table
ORDER BY
CASE WHEN date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB)) > DATE() then date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB))
ELSE date(strftime('%Y', date('now','+1 years')) || strftime('-%m-%d', DOB)) END
LIMIT 10;
user_id DOB
5 1996-08-27
10 1996-08-27
15 1996-09-27
13 2008-10-18
3 2008-11-18
8 2008-11-18
4 1998-01-02
9 1998-01-02
14 1998-01-02
1 2003-01-31
db<>fiddle here

How to create a query to get invoices between dates (help needed)

I need to create a query in SQL to get some invoices depending on the current date. I'm an intern in the company, so I only need to create the logic, not necessarily the query. Can anyone help me to translate this conditions into SQL (Snowflake)?
If Current Date (today's date) is between day 14 and 27 of the month >>> Get
invoices from day 14 of the current month
If Current Date (today's date) is between day 28 and 31 of the month >>> Get
invoices from day 28 of the current month
If Current Date (today's date) is between day 1 and 13 of the month >>> Get invoices
from day 28 of the last month
Thanks in advance!
I think your simplest, clearest option is a case statement.
You can put this into your select and work with it from there, or put it directly into a where clause. whatever's more appropriate for your query.
WHERE invoice_date::DATE = (CASE WHEN DAY(current_date) between 14 and 27 then DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 14)
WHEN DAY(current_date) between 28 and 31 then DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 28)
WHEN DAY(current_date) between 1 and 13 then DATEADD('month', -1, DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 28))
END)
select
current_date()+1 your_date
,dateadd(day,27-(sign(FLOOR(day(your_date)/14,0))*14)
,dateadd(month,sign(FLOOR(day(your_date)/14,0))-1
,date_trunc(month,your_date))) your_result
Revised solution.
Removing inequalities and reducing the problem down to multiples of 14 with month adjustments instead of multiple case statements (expensive to run at scale).

I want to get a specific answer by comparing two columns in postgresql

I have a query like this :
with base_data as
( Select
receipt_date,
receipt_value,
receipt_customer_id
From table1 )
Select
count(distinct (receipt_customer_id) , sum(receipt_value)
From
base_data
where
(receipt_date:timestamp <= current_date - interval '1 month' and
receipt_date: timestamp >= current_date - interval '2 month)
This basically gives me the number of distinct clients and their sum of receipt values for July and August considering the current month as September
I want to reduce this further and just want data for
distinct clients and sum of their receipt values
for whom there was no receipt in July i.e. they never transacted with us in July but came back in August basically they skipped a month and then transacted again.
I am unable to write this clause which I am putting in English below as a problem statement :
Give me the data for a distinct count of clients and their total sum of receipts who transacted with us in August but had no receipt value in July
I hope I am able to explain it. I have been racking my brain on this for a while but am unable to figure out a solution. Please help.
The current result looks like this
Count: 120
Sum: 207689
I want it reduced to (assumption)
Count: 12
Sum: 7000
The first issue I can see is with "sum of receipt values for July and August"; the return from your current query will depend upon when it is run (and will not be for calendar months). Lets put that aside and simplify/fix (the query as stated does not run) your query to one that will list all transactions in August (I think its simpler to understand using hard coded dates for now):
Select
receipt_customer_id, sum(receipt_value)
From
table1
where
-- Transacted in August
receipt_date >= '2020-08-01'::timestamp and
receipt_date < '2020-09-01'::timestamp
group by receipt_customer_id;
We can now add another clause to the where to filter out customers with transactions totalling $0/NULL (so total of $0 or no transactions at all) in July:
Select
receipt_customer_id, sum(receipt_value)
From
table1 t
where
-- Transacted in August
t.receipt_date >= '2020-08-01'::timestamp and
t.receipt_date < '2020-09-01'::timestamp
and (
select coalesce(sum(receipt_value), 0)
from table1
where
receipt_customer_id = t.receipt_customer_id and
-- Transacted in July
receipt_date >= '2020-07-01'::timestamp and
receipt_date < '2020-08-01'::timestamp
) = 0
group by receipt_customer_id;
or if you just want the count of customers and sum of receipt_value:
Select
count(distinct receipt_customer_id), sum(receipt_value)
From
table1 t
where
-- Transacted in August
t.receipt_date >= '2020-08-01'::timestamp and
t.receipt_date < '2020-09-01'::timestamp
and (
select coalesce(sum(receipt_value), 0)
from table1
where
receipt_customer_id = t.receipt_customer_id and
-- Transacted in July
receipt_date >= '2020-07-01'::timestamp and
receipt_date < '2020-08-01'::timestamp
) = 0
See this db fiddle for a test of this (feel free to use this if you want to ask follow-up questions). Note that if you want to reintroduce current_date you can do so (but you probably want to calculate the start of the month date_trunc can help with this).

Get Year of Previous Month (For Jan 1st)

I'm currently building a YTD report in SSRS. I'm looking to edit the default "FROM" date in a calendar selection.
I'm looking to retrieve January 1st of the previous months year. For example:
(If it's Feb 16th, 2016 .. the result should be 1/1/2016
If it's Jan 10th, 2016 .. the result should be 1/1/2015)
I built this to retrieve the current year for jan 1st, but it causes issues if we're in January because I need it to retrieve the year of the previous month (in that case it would be 2015, not 2016).
Thanks!
Try this, it should work
=DateAdd(DateInterval.Month,-1,DateSerial(Year(Today), Month(Today), 1))
UPDATE:
Based on your comment I've created this expression. It is not tested but should work.
=IIF(Today.Month>1,
DateAdd(DateInterval.Month,-1,DateSerial(Year(Today), Month(Today), 1)),
DateAdd(DateInterval.Year,-1,DateSerial(Year(Today), Month(Today), 1))
)
Let me know if this helps.
select cast(cast(year(dateadd(mm, -1,getdate())) as varchar)+'-01-01' as date)
replace getdate() with which ever field you're basing this calculation on.
for testing:
select cast(cast(year(dateadd(mm, -1,'2015-01-22')) as varchar)+'-01-01' as date)
select cast(cast(year(dateadd(mm, -1,'2016-02-01')) as varchar)+'-01-01' as date)
select cast(cast(year(dateadd(mm, -1,'2015-12-12')) as varchar)+'-01-01' as date)
We want to use Date Serial which has the forma
=DateSerial(YYYY,MM,DD)
The Month is always January
The day is always the first
If the month is January, it's last year. Otherwise, it's this year.
So, assuming we have an SSRS report with a parameter called Date , we can create a new field for your January date as follows:
=iif(Month(Parameters!Date.Value)=1,
dateserial(Year(Parameters!Date.Value)-1,1,1),
dateserial(Year(Parameters!Date.Value),1,1))
if you want to do this in the query with T-SQL (version 2012) or later:
case when month(#DATE) = 1
then DATEFROMPARTS(YEAR(#DATE)-1,1,1)
else DATEFROMPARTS(YEAR(#DATE),1,1)
end
OR, in earlier versions
CASE WHEN MONTH(#DATE) = 1
THEN CAST(CAST((YEAR(#DATE)-1)*10000 + 101 AS CHAR(8)) AS DATE)
ELSE CAST(CAST((YEAR(#DATE)*10000+ 101) AS CHAR(8)) AS DATE)
END

Select Date Between Just Day and Month Excluding Year

The following is the pseudo code for what I want to do:
When Date is Between 04-01 and 03-31 of the following year then output as Q1.
I know how to do this with the year but not excluding the year.
I have no idea what you mean by output "Q1". However, if you want your years to start on April 1st (which seems like a reasonable interpretation of what you are sking), the easiest way is to subtract a number of days. For most years you will deal with, you can do:
select year(dateadd(day, - (31 + 28 + 31), date) as theyear
Of course, this only works three years out of four, because of leap years. One way to fix this is with explicit logic -- but that gets messy. Another way is to add the remaining months and subtract one year:
select year(dateadd(day, (30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31), date) - 1 as theyear
It's unclear exactly what you're trying to do. Q1 usually indicates a quarter, a three-month period. A quarter running from 1 April to 31 March of the following year isn't much of a quarter :)
However, assuming you're trying to select stuff within a certain span of time starting from a particular date, you might try a little date/time arithmetic. First, a few notes:
datetime values have a nominal precision of 1 millisecond (and an actual precision of approximately 3ms). That means that something like '31 March 2014 23:59:59.999' is rounded up to '1 April 2014 00:00:00.000'. The largest time value for a given day is `23:59:59.997'. This can have...deleterious effects on your queries if you're not cognizant of it. Don't ask me how I know this.
datetime literals without a time component, such as '1 April 2013', are interpreted as start-of-day ('1 April 2014 00:00:00.000').
So, something like this:
declare
#dtFrom datetime ,
#dtThru datetime
set #dtFrom = '1 April 2013'
set #dtThru = dateAdd(year,1,dtFrom)
select *
from foo t
where t.someDateTimeValue >= #dtFrom
and t.someDateTimevalue < #dtThru
should probably do you.
You might want to adjust the setting of #dtThru to suit your requirements: if you're actually looking for the end of a quarter, you migh change it to something like
set #dtThru = dateAdd(month,3,dtFrom)
If you have a fiscal year that runs from 1 April through 31 March and want to figure out, say, what fiscal year and quarter your data represents, you might do something like this:
select FiscalYear = datepart(year,t.someDateTimeValue)
- case datepart(month,t.someDateTimeValue) / 4
when 0 then 1 -- jan/feb/mar is quarter 4 of the prev FY
else 0 -- everything else is this FY
end ,
FiscalQuarter = case datepart(month,t.someDateTimevalue) / 4
when 0 then 4 -- jan/feb/mar is Q4 of the prev FY
when 1 then 1 -- apr/may/jun is Q1 of the curr FY
when 2 then 2 -- jul/aug/sep is Q2 of the curr FY
when 3 then 3 -- oct/nov/dec is Q3 of the curr FY
end ,
*
from foo t
I think what you want is the following:
SELECT year(dateadd(q, -1, mydate)) AS yearEndingQ1
FROM mytable
This would give the year as 2014 for all dates between 04/01/2014 and 03/31/2015. Of course it's possible you want a result of 2015 instead in which case you want:
SELECT year(dateadd(q, 3, mydate)) AS yearEndingQ1
FROM mytable
Hope this helps.
UPDATE per OP's comment: "I am tracking data for a year ending Quarter x. Our fiscal year is a bit weird around here. So basically it would be fiscal year ending Q1, fiscal year ending Q2, etc. Perhaps I could have provided more clarity in my question."
This would give results in three separate columns for fiscal year ending Q1, fiscal year ending Q2, and fiscal year ending Q3. (I assume you don't need anything for fiscal year ending Q4!!)
SELECT year(dateadd(q, -1, mydate)) AS yearEndingQ1
, year(dateadd(q, -2, mydate)) AS yearEndingQ2
, year(dateadd(q, -3, mydate)) AS yearEndingQ3
FROM mytable