I just want to seek your help regarding the SQL Query below. I'm trying to compare Invoice date and Customer first Purchase Date. Supposedly if the the First Purchase Date is greater then Invoice Date but still within 1 year from the 1st Purchase Date, this will be categorize as New Business
For an example Customer A made a purchase on the following conditions
1st Purchase Feb 2021 -> New Business
2nd Purchase Oct 2021 -> New Business
3rd Purchase Jan 2022 -> New Business
4th Purchase Mar 2022 -> Existing Business (Since is more then 1 year after First Purchase)
Here are the Queries for CASE Scenario that I wrote
SELECT CASE
WHEN [FirstPurchaseCustomer] > [InvoiceDate] BETWEEN
DATEADD(Year,-1,FirstPurchaseCustomer) AND FirstPurchaseCustomer THEN
'New Business'
ELSE 'Existing Business'
END AS [Customer]
Related
I have purchase order data aggregated by items and month with the item's price for that month. I need to look back for the last month's price to find the difference in price. Not every item is purchased in every month (e.g. March 2020 is missing).
My approach is to add a new column to save the last month price, then add another new column to calculate the price change. But this may fail to be first normal form? Is there a better approach in terms of data structure?
Eventually this table will be fed into Power BI to report out the price changes by item. We want to do the calculations in SQL rather than in Power BI, and let Power BI focus on creating visuals.
Item
Month
Current price
Last month price
Price change
Item 1
Jan 2020
$1
-
-
Item 1
Feb 2020
$1.50
$1
$0.50
Item 1
Apr 2020
$1.75
-
-
Item 1
May 2020
$2
$1.75
$0.25
How can I generate a list of items that existed in one time period, but don't exist in a following time period. For example, a list of items that existed in January 2019, but did not appear in February 2019. I posted an idea of the sample query below, but I don't know how to approach this.
select period, item
from table
where period = 'February 2019'
and item (exists) in period -1
and item (does not exist) in period
Sample Data would be as follows (if there were three records, for example)
Period Item
January 2019 Bob
January 2019 Steve
January 2019 Phil
February 2019 Steve
February 2019 Phil
Desired results would be as follows:
Period Item
January 2019 Steve
Thank you for the help.
Based on your sample query, you should be able to use aggregation:
select item
from table
where period in ('February 2019', 'January 2019')
group by item
having min(period) = max(period) and
min(period) = 'January 2019';
You can use MONTH(yourdate) to get the month number and use that to get the desired results.
DECLARE #Month INT
SET #Month=1
SELECT * FROM
(SELECT * FROM #table WHERE month_number=#Month)current_period
LEFT JOIN
(SELECT * FROM #table WHERE month_number=#Month+1)following_period
ON
current_period.item=following_period.item
WHERE
following_period.item IS NULL
The SELECT after LEFT JOIN can be modified to Period_ID>#Month to include all the following periods.
I have a table with customer id and month of purchase. For each customer, I first need to segment them on their first month of purchase, i.e., if a customer did their first purchase on 10 June 2017, then they belong to bucket June 2017. See below sample data table.
Then for each subsequent purchase of that customer (say from June 2017 segment), we need to track the month. For instance, if the June 2017 customer did their second purchase on 25 June 2017 and 3rd purchase on 11 Aug 2017. Then second purchase will be counted in 1st Month (within 30 days of 1st transaction) and 3rd purchase will be counted in 3rd month, as difference between 11 Aug 2017 and 10 June 2017 is 62 days, which lies between 61 and 90 days, hence in the 3rd month.
See below sample output table, although I need it in percentage form (% of customer who did in first month, second month, etc.). In the table, we are showing all the customers who did their first transaction say in Jan 2017 and then how many of them did transactions in subsequent months.
This tracking needs to be done for each customer. While I believe I am comfortable with the first part, wherein I need to segment each customer, I can do that based on first or partition.
I am not sure about how to do this recursively for subsequent transactions.
Thanks in advance for help!
You simply use window functions to define the original month and then conditional aggregation.
You don't mention the database, but this is the idea:
select to_char(first_purchase_date, 'YYYY-MM') as yyyymm,
sum(case when months_between(first_purchase_date, purchase_date) = 1 then 1 else 0 end) as purchases_1,
sum(case when months_between(first_purchase_date, purchase_date) = 1 then 1 else 0 end) as purchases_2,
. . .
from (select t.*,
min(purchase_date) over (partition by customer_id) as first_purchase_date
from t
) t
group by first_purchase_date;
I invented the months_between() and to_char() functions, but you should get the idea.
The above tracks purchases. To get customers, you can use:
(count(distinct case when months_between(first_purchase_date, purchase_date) = 1 then customer_id) /
count(distinct customer_id)
) as month_1_ratio
You can use the lag function to create a column “previous purchase.
Lag(purchasemonth,1) over(partition. by customerid order by purchasemonth) as [PreviousPurchaseDate]
Then simply do a datediff and bucket as you wish.
I have a large data set (called input below) which contains a variety of information such as sales dates, transaction dates, payments, sales.
The user can produce a report by year, quarter or month to show the amount of payment in a particular month/quarter/year of a certain sales year. So you could have a payment 5 years after the initial sale, i.e. a payment in 2016 relating to the sales year of 2011.
The user can decide whether they want to have these payment periods by month/quarter/year at the beginning of the code through the use of macro variables (i.e. %let ReportBasis = Year) and ReportBasis can be called on through the rest of the code without manual adjustments.
The report is produced using:
proc sql;
create table report as
select sales_year, &ReportBasis, Sum(Sales) as Sales
from input
group by sales_year, &ReportBasis;
quit;
Now the issue I am having is that if there is no payment in a particular period for all sales years in question, then there is no row for that period. This produces a layout problem.
I require a solution to this which can be dynamic due to the nature of the macro variable (changing from year to month to quarter).
So I have this (example):
2011 Month 11 100
2011 Month 12 250
2011 Month 13 85
2011 Month 15 90
2011 Month 16 300
But I require this:
2011 Month 11 100
2011 Month 12 250
2011 Month 13 85
2011 Month 14 0
2011 Month 15 90
2011 Month 16 300
where there is no actual payment in month 14 in all of my data (even other years 2012, 2013 etc.), so it doesn't show up in my first table, but the second table still cleverly knows to include it.
Thanks in advance.
Here is one solution that assumes that all years and reports are represented in input, although not all combinations:
create table report as
select sy.sales_year, r.rb, Sum(i.Sales) as Sales
from (select distinct sales_year from input) sy cross join
(select distinct &ReportBasis as rb from input) r left join
input i
on i.sales_year = sy.sales_year and i.&ReportBasis = r.&ReportBasis
group by sy.sales_year, r.rb;
I would like to get a running tally of how many widgets were/are rented at any one time, by month, by year. Data is held in an MS Access 2003 db;
Table name: rent_table
Fields:
rentid
startdate
enddate
rentfee
rentcost
bookingfee
Something like; Count number of rentid's that fall between month/year, then group them?
e.g. if a widget was rented from 5th Jan 2014 to 8th April 2014 it would appear as a count in Jan, Feb, Mar and April tally's.
Many thanks.
EDIT
More details (sorry);
Access db is fronted by classic ASP.
If possible I don't want to create any new tables.
No input is required in order to run the report.
There are around 350-400 widgets that could be rented at any one time.
Each widget is rented exclusively.
Report output example;
Month | Year | NumRented
Jan 2014 86
Feb 2014 113
...
Can a query pick up dates within dates? So literally do a count of the table where date >Dec 31st 2013 AND <1st Feb 2014 (to grab a count for all of January 2014) and would that include the example of the rent starting on the 5th Jan? So I could just do twelve counts for each year?
create a calendar table, e.g.
table = cal_yyyymm with one column dt_yyyymm as numeric field
populate the table with ... say 5 or 10 years of data
201401 201402 201403 ... 60 or 120 rows, a small table
make a sql
Select
dt_yyyymm,
count(*) as cnt
From cal_yyyymm
Left Join rent_table
On format(startdate,"yyyymm") >= dt_yyyymm
And dt_yyyymm >= format(enddate,"yyyymm")
think about the complications in the data -- --
widget was rented from 5th Jan 2014 to 8th Jan 2014
and again rented from 11th Jan 2014 to 21st Jan 2014
does this count at 1 or 2 in the month?
if it is 1, then the sql gets more complicated because
the rent_table first needs to have its dates converted
to yyyymm format, and second needs to be de-duped on rentid,
and third then joined to cal_ On the dates...