How to compare two dates based on another column (SQL)? - sql

I am trying to compare the prelim_inbound ship date with the inbound ship date.
See data here
The end goal is just that I need to determine the how often the prelim date > inbound date, the prelim date = inbound date, the prelim date < inbound date to determine weather or not the manufacturers are shipping products early, late, or on time. I'm struggling trying to figure out how to do this.

You can use the DateDiff function:
datediff(dd,PrelimShipDate,InboundShipDate) as difference
You can use Case When to check if it's positive, negative or zero
case when datediff(dd,PrelimShipDate,InboundShipDate)>0 then 1
when datediff(dd,PrelimShipDate,InboundShipDate)=0 then 0
when datediff(dd,PrelimShipDate,InboundShipDate)<0 then -1 end as comparison
You could then count the 1s, 0s, & -1s for a how many of each if you like.

Related

Query with two different where conditions

I have a table books where users donate number of books:
username books date
____________________________________
Jon 3 2017-06-12
Jon 2 2017-05-20
Mary 4 2017-05-12
I want something like
username This month Previous Month
_______________________________________________
Jon 3 2
You will need some kind of grouping or conditional sum operations. The simplest way to get the result in your question - though which may not actually scale to your needs - is:
select username
,sum(case when dateadd(datediff(month,0,[date]),0) = dateadd(datediff(month,0,getdate()),0) then books else 0 end as ThisMonth
,sum(case when dateadd(datediff(month,0,[date]),0) = dateadd(datediff(month,0,getdate())-1,0) then books else 0 end as PreviousMonth
from books
where username = 'Jon'
group by username
Obviously with more details in your question you could get a better suited answer and one that is not specific to SQL Server should you be on a different DBMS. That said, the conditional and date logic is the same in all other DBMS implementations, you may just need to change the function names.
This works by adding the number of months between an arbitrary start date (the 0s in the functions above) and a date value to get the date at the start of the month. The dates returned by this logic for both your date value and today (the getdate() function) will return the same start of the month where they are both within the same calendar month. By adding one less month (the -1 in the script above) you get the start of last month, which you can then also compare to your date value to get the number of books for last month.
The sum and group by is there to 'flatten' your data into the one row per username value.

Creating a DAX pattern that counts days between a date field and a month value on a chart's x-axis

I am struggling with a DAX pattern to allow me to plot an average duration value on a chart.
Here is the problem: My dataset has a field called dtOpened which is a date value describing when something started, and I want to be able to calculate the duration in days since that date.
I then want to be able to create an average duration since that date over a time period.
It is very easy to do when thinking about the value as it is now, but I want to be able to show a chart that describes what that average value would have been over various time periods on the x-axis (month/quarter/year).
The problem that I am facing is that if I create a calculated column to find the current age (NOW() - [dtOpened]), then it always uses the NOW() function - which is no use for historic time spans. Maybe I need a Measure for this, rather than a calculated column, but I cannot work out how to do it.
I have thought about using LASTDATE (rather than NOW) to work out what the last date would be in the filter context of any single month/quarter/year, but if the current month is only half way through, then it would probably need to consider today's date as the value from which to subtract the dtOpened value.
I would appreciate any help or pointers that you can give me!
It looks like you have a table (let's call it Cases) storing your cases with one record per case with fields like the following:
casename, dtOpened, OpenClosedFlag
You should create a date table with on record per day spanning your date range. The date table will have a month ending date field identifying the last day of the month (same for quarter & year). But this will be a disconnected date table. Don't create a relationship between the Date on the Date table and your case open date.
Then use iterative averagex to average the date differences.
Average Duration (days) :=
CALCULATE (
AVERAGEX ( Cases, MAX ( DateTable[Month Ending] ) - Cases[dtopened] ),
FILTER ( Cases, Cases[OpenClosedFlag] = "Open" ),
FILTER ( Cases, Cases[dtopened] <= MAX ( DateTable[Month Ending] ) )
)
Once you plot the measure against your Month you should see the average values represented correctly. You can do something similar for quarter & year.
You're a genius, Rory; Thanks.
In my example, I had a dtClosed field rather than an Opened/Closed flag, so there was one extra piece of filtering to do to test if the Case was closed at that point in time. So my measure ended up looking like this:
Average Duration:=CALCULATE(
AVERAGEX(CasesOnly, MAX(DT[LastDateM]) - CasesOnly[Owner Opened dtOnly]),
FILTER(CasesOnly, OR(ISBLANK(CasesOnly[Owner Resolution dtOnly]),
CasesOnly[Owner Resolution dtOnly] > MAX(DT[LastDateM]))),
FILTER(CasesOnly, CasesOnly[Owner Opened dtOnly] <= MAX(DT[LastDateM]))
)
And to get the chart, I plotted the DT[Date] field on the x-axis.
Thanks very much again.

How to Calculate Sum untill start of month of a given date in DAX

I would like to calculate Sum(QTY) until the start date of the month for a given date.
Basically I can calculate Sum(QTY) until given date in my measure like:
SumQTYTillDate:=CALCULATE(SUM([QTY]);FILTER(ALL(DimDateView[Date]);DimDateView[Date]<=MIN(DimDateView[Date])))
But I also would like to calculate Sum(QTY) for dates before 10/1/2015 - which is the first date of selected Date's month. I have changed above measure and used STARTOFMONTH function to find first day of the month for a given date like;
.......DimDateView[Date]<=STARTOFMONTH(MIN(DimDateView[Date]))))
but not avail, it gives me
"A function ‘MIN’ has been used in a True/False expression that is
used as a table filter expression. This is not allowed."
What am I missing? How can I use STARTOFMONTH function in my measure?
Thanks.
STARTOFMONTH() must take a reference to a column of type Date/Time. MIN() is a scalar value, not a column reference. Additionally, your measure wouldn't work, because STARTOFMONTH() is evaluated in the row context of your FILTER(). The upshot of all this is that you would get a measure which just sums [QTY] across the first of every month in your data.
The built in time intelligence functions tend to be unintuitive at best. I always suggest using your model and an appropriate FILTER() to get to what you want.
In your case, I'm not entirely sure what you're looking for, but I think you want the sum of [QTY] for all time before the start of the month that the date you've selected falls in. In this case it's really easy to do. Add a field to your date dimension, [MonthStartDate], which holds, for every date in the table, the date of the start of the month it falls in. Now you can write a measure as follows:
SumQTY=SUM(FactQTY[QTY])
SumQTYTilStartOfMonth:=
CALCULATE(
[SumQTY]
;FILTER(
ALL(DimDateView)
;DimDateView[Date] < MIN(DimDateView[MonthStartDate])
)
)

Referencing a measure in DAX DATESBTWEEN function

In Powerpivot 2013 I am trying to calculate unit sales per day between the last time an item was received and the last time it was sold, but I keep getting tripped up by the DATESBETWEEN fuction.
These measures return the dates of of the last recieve and last sale:
Lastsale:=CALCULATE(LASTDATE(InvDetail[Date]), InvDetail[Type]="Sale")
Lastrecv:=CALCULATE(LASTDATE(InvDetail[Date]), InvDetail[Type]="Receive", all(InvDetail[Date]))
This is what I'm using to get the units sold between the last receive and last sale, but it's not working. I don't get an error, just crazy big numbers.
UnitsSold:=calculate(sum(InvDetail[units]), InvDetail[Type]="Sale", DATESBETWEEN(InvDetail[Date], [Lastrecv], [Lastsale]))
If I hard-code in the dates as below, it works.
UnitsSold:=calculate(sum(InvDetail[units]), InvDetail[Type]="Sale", DATESBETWEEN(InvDetail[Date], date(2015,1,1), date(2015,2,1)))
I also have to get the number of dates in that date range too, but I haven't gone there yet.
Is there some reason why I can't use the measures in the DATESBETWEEN function?
It's tricky without the data but my guess is that inside the DATESBETWEEN() you just aren't getting the expected filter context.
The first thing I would try is incorporating the measures in a CALCULATE() with a FILTER():
= CALCULATE(SUM(InvDetail[units]),
InvDetail[Type]="Sale",
FILTER(ALL(InvDetail[Date]),
InvDetail[Date] >= [Lastrecv] &&
InvDetail[Date] <= [Lastsale]
)
)
You could adapt this to count your dates with a DISTINCTCOUNT() on the date column instead of summing the units.

SQL query for finding a value in multiple ranges

i have MySQL db that contains event's date and 3 ranges, i.e from1-to1, from2-to2, from3-to3
each range has different price, i.e from1-to1 rate1 , from2-to2 rate2, ...
so that's 3 columns for each range: from, to and rate.
i'm trying to find the query that returns the rate for a given month, meaning finds the range that the month is in and returns the rate of that range.
any ideas?
thanks!
If you make an extra table just for the ranges you would keep your schema in normal form and you could easy select the right rate: TABLE range, COLUMNS from, to, rate. With a foreign key linking to your original table. Then you could SELECT rate FROM range WHERE 'date' >= from AND 'date' <= to.
It seems like your data model is not normalized. You should consider morjas suggestion about creating an additional table.
Below is a really ugly query that checks whether a date is in any of the three ranges, and then returns the matching rate.
select case
when date '2010-12-05' between range1_from and range1_to then range1_rate
when date '2010-12-05' between range2_from and range2_to then range2_rate
when date '2010-12-05' between range3_from and range3_to then range3_rate
end as rate
from events
where date '2010-12-05' between range1_from and range1_to
or date '2010-12-05' between range2_from and range2_to
or date '2010-12-05' between range3_from and range3_to;