Redshift - Joining two tables based on date ranges - sql

I have a table that stores date when product was bought and another table that states what offers were run during different time frames.
I am trying to join both these tables based on dates to find out if there was any sale during the date when purchase was made.
Given below is how much looks like:
Sale data:
prod_id,sale_date
1001,2019-02-02
1002,2019-05-04
1003,2019-03-04
1004,2019-04-21
Table that stores offers run by date is as below:
offer_name, start_date, end_date
offer_1,2019-01-02,2019-03-01
offer_2,2019-02-02,2019-03-06
offer_3,2019-04-01,2019-05-01
offer_4,2019-06-01,2019-07-01
I am trying to link the Sale data with the date when sale run data to get the below output:
prod_id,sale_date,offer_name
1001,2019-02-02,offer_1
1002,2019-05-04,
1003,2019-03-04,offer_2
1004,2019-04-21,offer_3

Its quite simple. You can simply use between to get the offer_name.
SELECT S.PROD_ID,S.SALE_DATE,O.OFFER_NAME
FROM Sale_data S
JOIN offers_run_data O
ON S.SALE_DATE BETWEEN O.START_DATE AND O.END_DATE

Related

Cohort retention with SQL BigQuery

I am trying to create a retention table like the following using SQL in Big Query but with MONTHLY cohorts;
I have the following columns to use in my dataset, I am only using one table and it's name is 'curious-furnace-341507.TEST.Test_Dataset_-_Orders'
order_date
order_id
customer_id
2020-01-02
12345
6789
I do not need the new user column and the data goes through June 2020 I think ideally a cohort month column that lists January-June cohorts and then 5 periods across.
I have tried so many different things and keep getting errors in BigQuery I think I am approaching it all wrong. The online queries I am trying to pull from seem to use dates rather than months which is also causing some confusion as I think I need to truncate my date column to months only in the query?
Does anyone have a go-to query that will work in BigQuery for a retention table or can help me approach this? Thanks!
This may help you:
With cohorts AS (
SELECT
customer_id,
MIN(DATE(order_date)) AS cohort_date
FROM 'curious-furnace-341507.TEST.Test_Dataset_-_Orders'
GROUP BY 1)
SELECT
FORMAT_DATE("%Y-%m", c.cohort_date) AS cohort_mth,
t.customer_id AS cust_id,
DATE_DIFF(t.order_date, c.cohort_date, month) AS order_period,
FROM 'curious-furnace-341507.TEST.Test_Dataset_-_Orders' t
JOIN cohorts c ON t.customer_id = c.customer_id
WHERE cohort_date >= ('2020-01-01')
AND DATE_DIFF(t.order_date, c.cohort_date, month) <=5
GROUP BY 1, 2, 3
I typically do pivots and % calcs in excel/ sheets. So this will give just you the input data you need for that.
NOTE:
This will give you a count of unique customers who ordered in period X (ignores repeat orders in period).
This also has period 0 (ordered again in cohort_mth) which you may wish to keep/ exclude.

SQL dynamic WHERE clause for every row

I need your expertise and guidance to understand the approach I should use to solve the task below. I have skimmed through existing answers but have not found good matches (unless they were there but they required extensive SQL knowledge and experience)
TASK
calculate total sales forecast per product for a period of time (from beginning of sales until end of end sales).
DATA
Table_1: Product - Calendar Week - Sales Forecast
Table_2: Product - Sales Start (Date_1, Individual for every product)
Table_3: Product - Sales End (Date_2, Individual for every product )
SOLUTION
My initial thought was to use simple WHERE BETWEEN clause but SQL crashes every time I execute the
SELECT
Product,
SUM(Sales_Forecast)
FROM Table_1 as T1
LEFT JOIN Table_2 as T2
ON T1.Product=T2.Product.
LEFT JOIN Table_3 as T3
ON T1.Product=T3.Product
WHERE T1.Calender_week BETWEEN T2.Sales_Start AND T3.Sales_End
GROUP BY Product
Thus the time period I am looking for is not static and it varies depending on a product and its start and end date of sales.
How should I better approach this task?
Thanks in advance,
f

How to display the sum of amount with between two given dates with groupwise, in Laravel?

I want to display the customer name and its sum of all the bills he paid between specific dates. I also want the whole list of customers between the 2 given dates with sum of their total bills.
In list what I want is first Customer Name then its regarding sum of all the bill totals.
I have tried many options for it one where I am getting the sum of that bill only every bill is appearing separately while I want to group it by the customer thats all.
Raw query is working in phpMyAdmin but I failed to convert it to Laravel Eloquent. I want to make this raw query to work using Eloquent.
Query:
select customer_id,sum(total),sum(totalcgst),sum(totalsgst),
sum(totaligst) from sales where
date BETWEEN '2018-03-01' and '2018-03-31'
group by customer_id
This is the result I am getting in database
Try this:
ORM_NAME::selectRaw('customer_id, sum(total), sum(totalcgst), sum(totalsgst)')->whereBetween('date', ['2018-03-01', '2018-03-01'])->groupBy('customer_id)->get();

SQL Select Items and link field to another table in same select

Currently I am retrieving a list of Purchase Orders Lines (POL) and each has a Due Date. For each line where the POL.Due Date is a future date i.e. >= Current Date, I need to determine the Period Name and Financial Week the POL.Due Date falls into.
The SQL Database has a table for the Financial Period and one for the Financial Week. Each table is driven by a date.
PERIODPER
PERIOD_DATE
PERIOD
PERIOD_NAME
PERIOD_YEAR
PERIOD_WEEK
START_DATE
WEEK
YEAR
Against each report line along with the Due Date I am trying to link to each of the above tables to determine the PERIOD_NAME and WEEK for the POL.Due Date.
Where the POL.Due Date has elapsed i.e. < Current Date, I need to retrieve the PERIOD_NAME and WEEK for the Current Date.
I would like to try and do this in an SQL select as my only other option is to write a VBA report which initially retrieves all the Purchase Order Lines and then serially reads through each and links to the other tables to determine the Financial Period Name and Week Number.
I am looking for an end result something on the lines of:
PO_NUMBER PO_LINE DUE_DATE WEEK_NO PERIOD_NAME
I would appreciate any assistance on this as my SQL knowledge does not extend to what to me appears to be a complex selection.
Do you mean something like this (SQL Server syntax)?
select pol.po_number,
pol.po_line,
pol.due_date,
pw.week as week_no,
pp.period_name
from purchaseOrderLines pol
left join period_week pw on pol.DueDate > GetDate()
and pw.start_date <= pol.due_date
and dateAdd(d, 7, pw.start_date) >= pol.due_date
left join periodPer pp on pol.DueDate > GetDate()
and pp.period_date = pol.DueDate
Thanks for your response.
I tried your logic which gave me what I was looking for but upon further investigation I located another table which detailed every date up to 2025, including the week and month. I'm simply now creating a JOIN to this new table using my Due Date value.
I would just like to thank you for your time and effort in answering my query. Although I am not using your suggestion for the stated example, I am however looking at what you've presented, and it certainly gives me a few ideas for some other SELECT statements I'm currently working on.

SQL how to implement if and else by checking column value

The table below contains customer reservations. Customers come and make one record in this table, and the last day this table will be updated its checkout_date field by putting that current time.
The Table
Now I need to extract all customers spending nights.
The Query
SELECT reservations.customerid, reservations.roomno, rooms.rate,
reservations.checkin_date, reservations.billed_nights, reservations.status,
DateDiff("d",reservations.checkin_date,Date())+Abs(DateDiff("s",#12/30/1899
14:30:0#,Time())>0) AS Due_nights FROM reservations, rooms WHERE
reservations.roomno=rooms.roomno;
What I need is, if customer has checkout status, due nights will be calculated checkin_date subtracting by checkout date instead current date, also if customer has checkout date no need to add extra absolute value from 14:30.
My current query view is below, also my computer time is 14:39 so it adds 1 to every query.
Since you want to calculate the Due nights upto the checkout date, and if they are still checked in use current date. I would suggest you to use an Immediate If.
The condition to check would be the status of the room. If it is checkout, then use the checkout_date, else use the Now(), something like.
SELECT
reservations.customerid,
reservations.roomno,
rooms.rate,
reservations.checkin_date,
reservations.billed_nights,
reservations.status,
DateDiff("d", checkin_date, IIF(status = 'checkout', checkout_date, Now())) As DueNights
FROM
reservations
INNER JOIN
rooms
ON reservations.roomno = rooms.roomno;
As you might have noticed, I used a JOIN. This is more efficient than merging the two tables with common identifier. Hope this helps !