Changes in Membership within date ranges - sql

As a newbie I was not sure how to post this and whether it is even suitable as a post. If not I apologize. I have been posed the following question. I tried my best with the tables, please advise if I did it wrong.
Account
Member
Membership_type
Start_Date
End_Date
Status
Year
100
1001
Premium
01/01/2022
05/31/2022
Terminated
2022
100
1001
Basic
06/01/2022
12/31/2022
Active
2022
200
2001
Premium
01/01/2022
03/31/2022
Terminated
2022
200
2001
Premium
01/02/2022
12/31/2022
Active
2022
300
3001
Basic
01/01/2022
02/28/2022
Terminated
2022
300
3001
Basic
04/01/2022
12/31/2022
Active
2022
Question:
From the above table, Member 1001 had a premium plan that ran from 01/01/2022 to 05/31/2022, and then the plan was terminated. In June they switched to a basic plan and would be active from June to Dec 2022. The consumer would have an Active and terminated count in the month of June due to the different plans. Member 2001 has two rows under the same plan, there was an issue with their membership and they terminated in April. Their membership was fixed under the same Membership type to show a correct start and end date range of 01/01/2022 thru to 12/31/2022. The row with the error should not be reported in the output. Member 3001 is similar to 1001 but there is a gap in the membership before they pick up the membership again.
Any ideas on how could achieve the output below from the table above.? I have shortened the output but it should show the status for the members each month unless their last action is to terminate their membership. In which case, it would show the termination month and no further reporting would occur for that member.
Member
Membership_Type
Status
Month
Year
1001
Premium
Active
Jan
2022
1001
Premium
Active
....
2022
1001
Premium
Terminated
June
2022
1001
Basic
Active
June
2022
1001
Basic
Active
....
2022
1001
Basic
Active
Dec
2022
2001
Premium
Active
Jan
2022
2001
Premium
Active
....
2022
2001
Premium
Active
Dec
2022
3001
Basic
Active
Jan
2022
3001
Basic
Active
Feb
2022
3001
Basic
Terminated
Mar
2022
3001
Basic
Active
Apr
2022
3001
Basic
Active
....
2022
3001
Basic
Active
Dec
2022

The first step is to generate a calendar table, with a row for each month in the range.
With that done, members 1001 and 3001 work with a simple JOIN. The trick is the double/corrected record for member 2001. We solve that by instead using a LATERAL JOIN/CROSS APPLY from the generated calendar data to your original table, where you take the TOP 1 best record that matches for each calendar month. In this way, Member 2001 can match the active plan in March and April, rather than the terminated plan, and show the correct result.

Related

Produce weekly and quarterly stats from a monthly figure

I have a sample of a table as below:
Customer Ref
Bear Rate
Distance
Month
Revenue
ABA-IFNL-001
1000
01/01/2022
-135
ABA-IFNL-001
1000
01/02/2022
-135
ABA-IFNL-001
1000
01/03/2022
-135
ABA-IFNL-001
1000
01/04/2022
-135
ABA-IFNL-001
1000
01/05/2022
-135
ABA-IFNL-001
1000
01/06/2022
-135
I also have a sample of a calendar table as below:
Date
Year
Week
Quarter
WeekDay
Qtr Start
Qtr End
Week Day
04/11/2022
2022
45
4
Fri
30/09/2022
29/12/2022
1
05/11/2022
2022
45
4
Sat
30/09/2022
29/12/2022
2
06/11/2022
2022
45
4
Sun
30/09/2022
29/12/2022
3
07/11/2022
2022
45
4
Mon
30/09/2022
29/12/2022
4
08/11/2022
2022
45
4
Tue
30/09/2022
29/12/2022
5
09/11/2022
2022
45
4
Wed
30/09/2022
29/12/2022
6
10/11/2022
2022
45
4
Thu
30/09/2022
29/12/2022
7
11/11/2022
2022
46
4
Fri
30/09/2022
29/12/2022
1
12/11/2022
2022
46
4
Sat
30/09/2022
29/12/2022
2
13/11/2022
2022
46
4
Sun
30/09/2022
29/12/2022
3
14/11/2022
2022
46
4
Mon
30/09/2022
29/12/2022
4
15/11/2022
2022
46
4
Tue
30/09/2022
29/12/2022
5
16/11/2022
2022
46
4
Wed
30/09/2022
29/12/2022
6
17/11/2022
2022
46
4
Thu
30/09/2022
29/12/2022
7
How can I join/link the tables to report on revenue over weekly and quarterly periods using the calendar table? I can put into two tables if needed as an output eg:
Quarter Starting
31/12/2021
01/04/2022
01/07/2022
30/09/2022
Quarter
1
2
3
4
Revenue
500
400
540
540
Week Date Start
31/12/2021
07/01/2022
14/01/2022
21/01/2022
Week
41
42
43
44
Revenue
33.75
33.75
33.75
33.75
I am using alteryx for this but wouldnt mind explaination of possible logic in sql to apply it into the system
Thanks
Before I get into the answer, you're going to have an issue regarding data integrity. All the revenue data is aggregated at a monthly level, where your quarters start and end on someday within the month.
For example - Q4 starts September 30th (Friday) and ends Dec. 29th (Thursday). You may have a day or two that bleeds from another month into the quarters which might throw off the data a bit (esp. if there's a large amount of revenue during the days that bleed into a quarter.
Additionally, your revenue is aggregated at a monthly level - unless you have more granular data (weekly, daily would be best), it doesn't make sense to do a weekly calculation since you'll probably just be dividing revenue by 4.
That being said - You'll want to use a cross tab feature in alteryx to get the data how you want it. But before you do that, we want to aggregate your data at a quarterly level first.
You can do this with an if statement or some other data cleansing tool (sorry, been a while since I used alteryx). Something like:
# Pseudo code - this won't actually work!
# For determining quarter
if (month) between (30/09/2022,29/12/2022) then 4
where you can derive the logic from your calendar table. Then once you have the quarter, you can join in the Quarter Start date based on your quarter calculation.
Now you have a nice clean table that might look something like this:
Month
Revenue
Quarter
Quarter Start Date
01/01/2022
-135
4
30/09/2022
01/01/2022
-135
4
30/09/2022
Aggregate on your quarter to get a cleaner table
Quarter Start Date
Quarter
revenue
30/09/2022
4
300
Then use cross tab, where you pivot on the Quarter start date.
For SQL, you'd be pivoting the data. Essentially, taking the value from a row of data, and converting it into a column. It will look a bit janky because the data is so customized, but here's a good question that goes over pivioting - Simple way to transpose columns and rows in SQL?

Sort SQL by value

I have data like this:
Customer ID
Name
Type
Last Submit
1
Patricio
C
January 2022
2
Dale
A
June 2022
3
Yvonne
C
July 2022
4
Pawe
C
JUne 2022
5
Sergio
B
August 2022
6
Roland
C
August 2022
7
Georg
D
November 2022
8
Catherine
D
October 2022
9
Pascale
E
October 2022
10
Irene
A
November 2022
How to sort type A out of the queue first like A,B,C,D,E,F, then the last submit is at the top.
The example output:
Customer ID
Name
Type
Last Submit
10
Irene
A
November 202[![enter image description here][1]][1]2
1
Dale
A
June 2022
5
Sergio
B
August 2022
6
Roland
C
August 2022
3
Yvonne
C
July 2022
4
Pawe
C
June 2022
1
Patricio
C
January 2022
7
Georg
D
November 2022
8
Catherine
D
October 2022
9
Pascale
E
October 2022
So basically you want to sort by 2 different columns, this is detailed in this other answer: SQL multiple column ordering
In your example you would do
ORDER BY type, last_submit
Hi you can use simple order by in postgresql
like this
SELECT
*
FROM
table (your table name)
ORDER BY
type ASC, last_submit DESC;
In this case, you need to sort your query using the two columns in order.
Add this part to the end of your query.
ORDER BY type, last_submit DESC;
Check out this question "SQL multiple column ordering"

Complex Logic- Finding Renewals on Licenses

Need help in querying the below logic:
I have to calculate renewals. An org can order up to 5 licenses in total from us
License Table 2018
Year
Licenses
2018
A
2018
A
2018
B
2018
B
2018
C
2019
A
2019
A
2019
B
License Table 2019:
Year
Licenses
2019
A
2019
A
2019
B
Result:
License
Renewal Percentage
A
100%
B
50%
C
0%
More conditions:
Suppose the 2 order dates are 6/30/2019 and 7/1/2020, which are in FY19 and FY21 respectively. Even though the 2nd order is barely more than 1 year later, it is not treated as a renewal.

Filter Data by Date

I have question to ask. Currently, I'm developing a payslip application. However, I stuck at 1 part of the process. I'm managed to display salary but I need to filter certain date in order for the salary to be display.
For example, for this September, the company already key in the salary on 26th Sep but user can only see it start from 28th Sep and above. So, basically, the program can show previous month payslip except for September unless user start see it on 28th Sep.
Current Output :
EMPLOYEEID MONTH YEAR SALARY
E001 7 2017 2000
E001 8 2017 2000
E001 9 2017 2000
E002 7 2017 2100
E002 8 2017 2100
E002 9 2017 2100
Expectation output:
EMPLOYEEID MONTH YEAR SALARY
E001 7 2017 2000
E001 8 2017 2000
E002 7 2017 2100
E002 8 2017 2100
Current Query Progress :
SELECT EMPLOYEEID, MONTH, YEAR, SALARY
FROM DBO.Salary
WHERE day(getdate())>=28
Today is 2017-09-29, do Sep should appear. Add the OR for when it's less than 28th
select *
from dbo.Salary s1
where day(getdate())>=28
or month(getdate()) > s1.Month

Normalize monthly payments

First, sorry for my bad English. I'm trying to normalize a table in a pension system where subscribers are paid monthly. I need to know who has been paid and who has not and how much they've been paid. I believe I'm using SQL Server. Here's an example:
id_subscriber id_receipt year month pay_value payment type_pay
12 1 2016 January 100 80 1
13 1 2016 January 100 100 1
14 1 2016 January 100 100 1
12 2 2016 February 100 100 2
13 2 2016 February 100 80 1
But I'm not happy repeating the year and the month for every single subscriber. It doesn't seem right. Is there a better way to store this data?
EDIT:
The case is as follows: this company has many subscribers who must pay monthly and payment can be in various ways. They produce a single receipt for many customers, and each customer that receipt may be paying one or more installments.
These are my other tables:
tbl_subscriber
id_suscriber(PK) first_name last_name address tel_1 tel_2
12 Juan Perez xxx xxx xxx
13 Pedro Lainez xxx xxx xxx
14 Maria Lopez xxx xxx xxx
tbl_receipt
id_receipt(PK) value elaboration_date deposit_date
1 1,000.00 2015-09-16 2015-09-20
2 890.00 2015-12-01 2015-12-18
tbl_type_paym
id type description
1 bank xxxx
2 ventanilla xxx
This basically seems fine. You could split dates out into a separate table and reference that, but that strikes me as a kind of silly way to do it. I would recommend storing the month as an integer instead of a varchar column though. Besides not storing the same string over and over you can more reasonably do comparisons.
You could also use date values, although that might not be worth the trouble when you don't want greater granularity than the month.