Report Next Date in Sequence - sql

Our database keeps track of only 5 billing payments received each month. How can I write a select statement that will look, sequentially, at each payment received date and if there is a date entered to move on the the next payment, etc...then eventually come across the date with an empty field and report that date?
I've tried the following case statement but think I am on the wrong track;
select db.identifier,
case when recdate1 is not null then recdate1
when recdate2 is not null then recdate2
when recdate3 is not null then recdate3 end
from db

You should use the COALESCE function for this. The COALESCE function will take n number of input fields, and return the first NOT NULL input field from left to right. In other words, if you sequence the recdate fields from recdate1 to recdate 5, it will return the first one that is NOT NULL.
Here is the code to achieve this.
SELECT db.identifier
, COALESCE(recdate1, recdate2, recdate3, recdate4, recdate5) AS recdate
FROM mytable
Here is a link to the COALESCE function for more information. Hope this helps.
https://msdn.microsoft.com/en-us/library/ms190349.aspx

Related

Sum case when like then

I am using a dataset on BigQuery and essentially I would like to pull a table to show the total volume of liters sold per month of a specific year. This is currently what I have written:
SELECT
SUM( CASE WHEN `date` LIKE '2012-01-%' THEN `volume_sold_liters` END) as Jan_Total
FROM `personal-projects-340200.Iowa_liquor_cedar_rapids.store_3`
This is the error message I am also getting:
No matching signature for operator LIKE for argument types: DATE, STRING. Supported signatures: STRING LIKE STRING; BYTES LIKE BYTES at [2:16]
I understand that the error message is asking for me to change the string to a date but how do I do that? I have multiple dates in the same month that I want added together. I tried to switching the date to a string instead and I get NULL in my table.
What am I doing wrong? Is there a better way to go about pulling the table I want?
You can use the dedicated date functions offered by BigQuery in your case. Since you want the month part of the purchased date you can consider something like the query below
SELECT
SUM(CASE
WHEN DATE_TRUNC(purchase_date, MONTH) = '2022-01-01' THEN volume
ELSE 0
END
) AS Jan_Total
FROM
`personal-projects-340200.Iowa_liquor_cedar_rapids.store_3`
The error you get is because you try to compare a DATE to a STRING. To fix this you could go for
SELECT
SUM(CASE
WHEN CAST(purchase_date AS STRING) LIKE '2022-01-%' THEN volume
ELSE 0
END
) AS Jan_Total
FROM
`personal-projects-340200.Iowa_liquor_cedar_rapids.store_3`
But it's better to use date functions when manipulating dates.

Group by: calculated field to return respective date in bigquery

I need to do an user level analysis. As the data has a lot of different rows per user (related to different events), I need to group by user and create some calculated fields that represent the different rows. One of the fields is a calculation of the number of days since the last purchase of the user (today - last purchase date). I already tried a lot of different codes and also did a lot of research, but could not find the solution.
The codes that for me makes more sense but did not work are below:
Using case when statement
SELECT CASE WHEN LAST(tr_orderid <> "") THEN
DATEDIFF(CURRENT_DATE(),event_date) ELSE NULL END AS recency_lastbooking
FROM df
GROUP BY domain_userid
Using IF statement
SELECT IF(LAST(tr_total > 0), DATEDIFF(CURRENT_DATE(),event_date), NULL)
AS recency_lastbooking
FROM df
GROUP BY domain_userid
The error that I get is: Expression 'event_date' is not present in the GROUP BY list
I think if I use LAST(event_date) the query will return the last date in all the lines of the specific user, instead of return the last day the user had a purchase event.
P.S: I can use tr_total (total transaction) > 0 or tr_orderid (transaction order id) <> ""
Thank you!
I think you just want a window function:
SELECT DATE_DIFF(CURRENT_DATE,
MAX(tr_orderid) OVER (PARTITION BY domain_userid),
day
) AS recency_lastbooking
FROM df;

SQL find nearest date without going over, or return the oldest record

I have a view in SQL Server with prices of items over time. My users will be passing a date variable and I want to return the closest record without going over, or if no such record exists return the oldest record present. For example, with the data below, if the user passes April for item A it will return the March record and for item B it will return the June record.
I've tried a lot of variations with Union All and Order by but keep getting a variety of errors. Is there a way to write this using a Case Statement?
example:
case when min(Month)>Input Date then min(Month)
else max(Month) where Month <= Input Date?
Sincere apologies for attaching sample dataset as an image, I couldn't get it to format right otherwise.
Sample Dataset
You can use SELECT TOP (1) with order by DATE DESC + Item type + date comparison to get the latest. ORDER BY will order records by date, then you get the latest either this month (if exists) or earlier months.
Here's a rough outline of a query (without more of your table it's hard to be exact):
WITH CTE AS
(
SELECT
ITEM,
PRICE,
MIN(ACTUAL_DATE) OVER (PARTITION BY ITEM ORDER BY ITEM) AS MIN_DATE,
MAX(INPUT_DATE<=ACTUAL_DATE) OVER (PARTITION BY ITEM ORDER BY ITEM,ACTUAL_DATE) AS MATCHED_DATE
FROM TABLE
)
SELECT
CTE.ITEM,
CTE.PRICE,
CASE
WHEN
CTE.MATCHED_DATE IS NOT NULL
THEN
CTE.MATCHED_DATE
ELSE
CTE.MIN_DATE
END AS MOSTLY_MATCHED_DATE
FROM CTE
GROUP BY
CTE.ITEM,
CTE.PRICE
The idea is that in a Common Table Expression, you use the PARTITION BY function to identify the key date for each item, record by record, and then you do a test in aggregate to pull either your matched record or your default record.

Calculating Percentage when Row can contain 0

I have previously asked the following question: Calculating percentage within the SQL
Now i was lucky enough to get a great answer however in my question i did not take into account that my rows could contain zero.
The questions row where simple:
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/Number_Of_Calls)*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
However Number_of_answered could be zero (if our company did not answer the calls) so if i want the full number in percentage how do i take 0 into account?
By the way. The database that we use is an Oracle database with PL SQL
The nullif function can be used to return null if the divisor is zero. When SQL encounters a null divisor it forces the entire equation to return null, preventing your error from occurring.
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
If you would like to exclude null percentages use the following SQL:
select * from(select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11') alias
where answer_percent is not null;
Case when Number_Of_Calls = 0
THEN 0 --or your desired value, maybe 100
else (Number_of_answered/Number_Of_Calls)*100
END as answer_percent
i think you mean "Number_Of_Calls" could be zero (thus raising a zero_divide error?) if so do
case Number_Of_Calls when 0 then 0 else ((Number_of_answered/Number_Of_Calls)*100) as answer_percent
As far as I understood you from your comment you want a rate of answered calls over a period of time, including days when 100% calls were unanswered.
I guess the simpliest approach would be
select sum(number_of_answered) / sum (number_of_calls)
from table
where date between interval_start and interval_end
in this case.

SQL Server Query Explanation

I am working on code from a person who held my position 2+ years ago, and am having trouble deciphering a block of their SQL code.
WHERE ACCOUNT NOT IN (SELECT ACCOUNT
FROM MWAPPTS A1
WHERE A1.ACCOUNT = A.ACCOUNT
AND ADATE > dbo.Endofmonth(ACTIONDATE)
AND REASON IN ('CPE','NPPE')
AND USERFLAG IN ( 'U', 'B' ))
dbo.Endofmonth is a stored procedure which gets the last day of the month for the inputed date.
If I am reading that right, we are not including rows where the account would be returned by the select statement shown. I am having problems with the select statement though. Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month. The reason IS "CPE" or "NPPE", and the USERFLAG is either "U", or "B"?
Yes, you are returning the records where the account does not have the following:
1) an ADATE greater than the date returned by the function dbo.Endofmonth(ACTIONDATE).
2) a Reason that is CPE or NPPE
3) and the Userflag is either U or B.
You would have to look at the code in the function dbo.Endofmonth(ACTIONDATE) to determine exactly what it is returning.
Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month.
The inner SELECT itself is looking for entries where ADATE is after the end of the month from ACTIONDATE. The NOT IN in the outer SELECTshould then retrieve rows where the account's ADATE is <= the end of the month from ACTIONDATE.
Your other assumptions seem correct.
Aside: It seems dbo.Endofmonth is a User-Defined Function, not a stored procedure (or it wouldn't be possible to call it like that).