Get month from date time now month, Get year from date time now year and write specific day - sql

Hello everyone i want search data from invoices and client by today date I'm using DateDiff() GETDATE() functions for example two tables
1 Client
- ID int
- Name Varcher
2 Invoice
- ID int
- ClientID int
- date Datetime
- Total money
query
Select * from client c
inner join invoice i on c.id = i.ClientID
WHERE DateDiff(dd, i.date, getdate()) = 0
when i run query the getdate() it is function to get date from date time now
the date content current month and current year and current day
when i run query today the date is 08-23-2010, when i run query tomorrow the date is 08-24-2010.
Q - the query do something equal date i want get month from date time now month, get year
from date time now year and write specific day only.

I do not understand your question clearly, but as far as I understand you want to have a time difference other than 0 days. You would then have to use other dateparts (first argument to DateDiff()) See the MS documentation of DateDiff for details, or the DateAdd function.
Furthermore, maybe you want to use
i.date between DateAdd(dd, -10, getDate) and getDate()
(which would show everything between ten days ago and today).

declare #day integer
select #day = 10
Select * from client c
inner join invoice i on c.id = i.ClientID
WHERE
DateDiff(dd, i.date, dateadd(dd,#day-datepart(dd,getdate()),getdate())) = 0

Related

Generate List of dates between 2 dates for each Id

I have a table with PersonId's that each have a FirstSubscription date and LastSubscriptionDate.
What I need to do is between those 2 dates, generate 1 date for each month. This is for reporting purposes on the front end, as this data will end up inside PowerBI and I need these dates to join to a ReportingCalendar.
This Calendar is accessible by SQL so it can be used in this calculation. I am using it to generate the dates (using first of the month) between the First and LastSubDate but I need to find a way to join this with the rest of the ID's that way I get a list of date for each ID.
Here is my code to generate the dates.
DECLARE #MinDate DATE
DECLARE #MaxDate DATE
SET #MinDate = '2020-08-31'
SET #MaxDate = '2022-08-30'
SELECT DATEADD(month, DATEDIFF(month, 0, date), 0)
FROM dbo.ReportingCalendar
WHERE Date >= #MinDate
AND Date < #MaxDate
GROUP BY
DATEADD(month, DATEDIFF(month, 0, date), 0)
My PersonSubscription table looks like this
|PersonId|FirstSubDate|LastSubDate|
|--------|------------|-----------|
|1186 |8/31/2020 |8/30/2022 |
|2189 |7/30/2019 |7/31/2021 |
So I would want to end up with an output where each PersonId has 1 entry for each month between those 2 dates. So PersonId has 25 entries from 8/2020 until 8/2022. We don't care about the actual date of the sub since this data is looked at monthly and will primarily be looked at using a Distinct Count each month, so we only care if they were subbed at any time in that month.
I just needed to do a Cross Apply.
I took my code that got me all of the PersonId's and their FirstSubDate and LastSubDate and then did a cross apply to the code I listed above, referencing the MinDate and MaxDate with the FirstSubDate and LastSubDate.

Can you pull from before a casted time

sql newbie here. I'm trying to make a report for a tracking software where assets go into the database with a "Status" and a time stamp when they make that change.
What I'm trying to do is write a report that tells me when something hits the status 'complete' but its origin status was a month prior. How would I go about getting this to work properly with declaring a start and end date?
Declare #StartDate datetime
Declare #EndDate datetime
-- Set the start and end dates here yyyy-mm-dd --
set #StartDate = '2021-08-01'
set #EndDate = '2021-08-31'
Select *
from assetcurrent.dbo ac
inner join (select assetid, min(hdate) as [hdate] from history where hstatus = "created" group by assetid, hdate) ah
Where a.status in ('complete')
and cast(ac.hdate as date) <= cast(#EndDate as date)
and cast(ac.hdate as date) >= cast(#StartDate as date)
and ah.hdate < dateadd(month, -1, #StartDate)
order by [Report number]
Am I properly using dateadd here in the where clauses? I just get 0 results when I know there should be at least a few.
Thanks!
--and ah.hdate < dateadd(month, -1, #StartDate)
Was what i was trying and giving me failed results.
and MONTH(ac.hdate) != month(ah.hdate)
Is what i should have used instead. much simpler.
Correct me if I'm wrong.
Please clarify for month prior. Ex, something ordered on Sept 30 and Completed on Oct 1 is only 1 day, yet in the prior month. Is your question really what projects too longer than, ex: 30 days, to be completed? Much more specific condition. Also, are you looking for completed tasks such as Completed within September 2021 that took more than 30 days from the order/project start date?
select
AC.*,
PQ.DateCreated,
PQ.DateCompleted
from
( select
h.assetid,
MIN( h2.hdate) as DateCreated,
min(h.hdate) as DateCompleted,
from
history h
JOIN history h2
ON h.assetid = h2.assetid
AND h2.status = 'created'
AND h2.hdate < dateadd( month, -1, h.hdate )
where
h.hstatus = 'complete'
AND h.hdate >= '2021-09-01'
AND h.hdate < '2021-10-01'
group by
h.assetid ) PQ
JOIN AssetCurrent AC
ON PQ.assetid = AC.assetid
order by
ac.[Report Number]
So, in the query above, I am starting to look for all orders COMPLETED within the given time period (changed to Sept 1 to Sept 30). From that, I joined secondary to same history table again with alias h2 on the same asset ID, but this time based on when it was originally created. Now, I have a record of complete and created that I am looking at. From that, I can now apply the h2.date being LESS than a month prior to its creation. So in an example of an order was complete on Sept 27, it would only return the same asset if it was ordered prior to Oct 27, thus took more than a month to complete.
Once I had that part resolved, I could then join to your AssetCurrent table based on an implied key of assetid to get those details. While at it, I grabbed both context of Created and Completed Dates in the return set.

Matching date with calculated DATEADD date

I am trying to create a table with columns containing the current date, prior year date, and additional column for the total sum revenue as below:
cur_date | py_date | py_rev
I'm trying to compare revenue across any daily period across years. Assume all dates and revenue values are included in the same SQL Server table.
I attempted to use a case statement using [date] = DATEADD(wk,-52,[date]) as the condition to return the appropriate total. The full line code is below:
select
[date] as cur_date,
DATEADD(wk,-52,[date]) py_date,
SUM(case when [date] = DATEADD(wk,-52,[date]) then sum_rev else 0 end) as py_rev
from summary
group by [date]
When running this code the py_date is as expected but py_rev returns 0 as if there is no match. What's most confusing is if I hard code a random date in place of the DATEADD portion then a total is returned. I have also tried CAST to format both date and the DATEADD portion as date with no luck.
Is there something about DATEADD that will not match to other date columns that I'm missing?
If you want the previous years revenue, then lag() is one method. This works assuming that "previous year" means 52 weeks ago and you have records for all dates:
select [date] as cur_date,
dateadd(week, -52, [date]) as py_date,
lag(sum_rev, 52 * 7) over (order by date) as py_rev
from summary;
If you do not have records for all dates, then another approach is needed. You can use a LEFT JOIN:
select s.date, dateadd(week, -52, s.[date]),
sprev.sum_rev as py_rev
from summary s left join
summary sprev
on sprev.date = dateadd(week, -52, s.[date]);

SQL to use getdate() to declare a variable to run a comparison against in SAP B1

I have a SAP B1 installation and I have a user table consisting of WeekNo, DateFrom, DateTo ...
It lists all the week numbers for each year, so the first week of the year is 202001 (yyyyww) and is set DateFrom 01/01/2020 and DateTo 07/01/2020
I am using getdate() to fetch todays date and using that to get the current week number.
What I am unable to see past is how to set the current week number to run a comparison against.
I have agoods in table also which has a field and is auto populated with the week number when it is created.
I need to be able to run this query without the user needed to enter the date or week number and for it to return all the goods in records for the current week.
So, getdate() to fetch the current week.
Compare that returned week (as a string) to all the week numbers (as a string) against all the goods in records and return where it matches.
Here is my sql, which is very incomplete.
getdate() as 'Date',
T1.[ItemCode],
T1.[Quantity]
FROM
OPDN T0
INNER JOIN PDN1 T1 ON T0.[DocEntry] = T1.[DocEntry]
INNER JOIN [dbo].[#DATE] T2 ON T0.[U_Wk] = T2.[Code]
WHERE getdate() BETWEEN T2.U_From and T2.U_to
AND T1.[ItemCode] NOT Like '%%STAT%%'
To explain the tables
T1.[Quantity] <-- number of each
T0/T1.[DocEntry] <-- GR record ID
T0.[U_Wk] <-- week number on the GR
T2.[Code] <-- week number used for the getdate() clause
T2.U_From and T2.U_to <-- dates that denote the week start and end
my apologies if I have misunderstood your question but this should help:
get current week
select DATEPART(wk, GETDATE())
get the document week number
select datepart(week, DocDate) from ORDR
for example
declare #thisWeek as nvarchar = cast(DATEPART(wk, GETDATE()) as nvarchar)
select
docnum
from ORDR
where cast(datepart(week, DocDate) as nvarchar) = #thisWeek

Finding orders made within any ISO week of a specific year using T-SQL

As part of a reporting setup, I have a SQL query fetching the number of orders placed each week:
select datepart(isowk, order_date), count(*)
from orders where year(order_date) = #Year
group by datepart(isowk, order_date), year(order_date)
order by 1
Note that I am using the new isowk format in the datepart function call, as business in Denmark typically use ISO week numbers.
Running this query with #Year = 2010 yields a result set simialar to this:
1 5
2 7
3 10
...
53 3
You and I both know that 2010 isn't over yet, and certainly there has been no week 53 yet. Actually, there has - the first three days of the year belonged to ISO week 53 of 2009. While it might be possible to explain this to other programmers, the people who are going to read my reports are never going to understand this. Hence, I want to get rid of this week 53, by "moving" the data over to 2009.
How can I rewrite my WHERE clause to filter the data set to orders made between monday of week 1 and friday of the last week (52 or 53) in the year defined as #Year?
In fact I do not know any programming language which delivers a isoyear ...
create function isoyear(#date datetime) returns smallint as begin
declare #isoyear smallint =
case
when datepart(isowk, #date) = 1 and month(#date) = 12
then year(#date)+1
when datepart(isowk, #date) = 53 and month(#date) = 1
then year(#date)-1
else year(#date)
end;
return #isoyear;
end;
Hope we'll get a datepart(isoyear, ...) next time ...
You could try this:
set datefirst 1;
declare #Year smallint = 2010;
declare #DayInFirstWeek datetime = cast(#Year as varchar)+'0104';
declare #FirstDayInFirstWeek datetime =
#DayInFirstWeek - datepart(dw,#DayInFirstWeek)+1
declare #DayInFirstWeekNextYear datetime = cast(#Year+1 as varchar)+'0104';
declare #LastDayInLastWeek datetime =
#DayInFirstWeekNextYear - datepart(dw,#DayInFirstWeekNextYear);
select datepart(isowk, order_date), count(*)
from orders
where order_date between #FirstDayInFirstWeek and #LastDayInLastWeek
group by datepart(isowk, order_date)
order by 1;
If your first day of week isn't Monday it perhaps won't work!
Do an IF statement - I don't guarantee the SQL server syntax, but:
// IF ISO week is 53, return week 1 of next year.
GROUP BY IF(datepart(isowk, order_date)) = 53,
CONCAT("1/", year(order_date) + 1),
CONCAT(datepart(isowk, order_date), "/", year(order_date))
I am going to take a stab at this myself, using the approach described in my comments on Manfred's answer. The idea is to find the first day of the first ISO week of the specified year and the year after, allowing for index-enabled between filtering of the input records.
First, I create a function which will find the first day of the first ISO week in a specific year:
create function firstIsoDay(#year int) returns datetime as begin
declare #first datetime
select #first = cast(cast(#year as char(4)) as datetime)
select #first = dateadd(ww, datediff(ww, 0, #first), 0)
if datepart(isowk, #first) > 1 set #first = #first + 7
return #first
end
Disclaimer: This function is untested (having no Sql Server 2008 available at the moment).
The actual data query can then be made using two invocations of this function in a between filter:
select datepart(isowk, order_date), count(*) from orders
where order_date between firstIsoDay(#Year) and firstIsoDay(#Year + 1)
group by datepart(isowk, order_date), year(order_date)
order by 1
Remember that between is two-way inclusive. If the values in order_date contain truncated dates (no time), -1 should be added to the end of the where clause. In my use case, order_date has both date and time, so between two dates at midnight should do just fine.
Just to spell out the fundamental answer here:
If you are querying based on ISO weeks, you must filter based on ISO Year (and not calendar year)
How you add an ISO year column to your data (or where clause) is as others have described.