Skip the day the email was opened and count 7 days after open in big query SQL - sql

I am trying to block off a window within my script that will attribute a sale to a 7-day window. The issue that I am having is that I want the seven-day window to not include the open date so open date = 0 and the sales window begins on day 1.
Here is the current way that I am creating that window -
and oh.Order_Date >= first_open_date.first_open
and oh.Order_Date <= first_open_date.first_open + 7

If you can provide some example data I can help with a more accurate answer, but for now I hope the below will share some ideas.
Please consider the below approach, where I'm assuming your 'opens' refer to tracking whether a user has opened a marketing campaign.
select orders.*,campaigns.campaign_name
from orders_table as orders
left join
(
select distinct timestamp as open_date,campaign_name from campaign_data
) as campaigns
on orders.user_id = campaigns.user_id and campaigns.open_date < orders.order_date and campaigns.open_date >= date_sub(orders.order_date,interval 7 day)
This example is based on something similar to what I've created for work in the past, which looks at each order date in the order table and then what campaigns were opened before that date.
You may also want to consider using a window statement like row_number or dense_rank with this if you wish to pull only the first or last campaign that was opened to answer questions like "What was the last google ad a user interacted with before placing an order".
Hope this helps,
Tom

Related

Oracle SQL - Calculating days passed by different user IDs

I desperately need some help from your brains to solve one SQL problem I have now.
I have a very simple table made of two columns: Client # and Purchasing Date.
I want to add one more column to show how many days have passed since the previous Purchasing Date per each Client #. Below is my current query to create the starting table.
select client_id, purchasing_date
from sales.data
The result looks like this (apparently, I need more reputation to post images):
https://imgur.com/a/IP1ot
The highlighted column on the right is the column I want to create.
Basically, that shows the number of days elapsed since the previous purchasing date of each Client #. For the first purchase of each Client, it will be just 0.
I'm not sure if I have explained enough to help you guys produce solutions - if you have any questions, please let me know.
Thanks!
Use lag():
select client_id, purchasing_date,
(purchasing_date -
lag(purchasing_date, 1, purchasing_date) over (partition by client_id
order by purchasing_date
)
) as day_diff
from sales.data

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.

Monthly Moving Average of User Activity in SQL Server Using Window Functions

Let's say I have a table UserActivity in SQL Server 2012 with two columns:
ActivityDateTime
UserID
I want to calculate number of distinct users with any activity in a 30-day period (my monthly active users) on a daily basis. (So I have a 30-day window that increments a day at a time. How do I do this efficiently using window functions in SQL Server?
The output would look like this:
Date,NumberActiveUsersInPrevious30Days
01-01-2010,13567
01-02-2010,14780
01-03-2010,13490
01-04-2010,15231
01-05-2010,15321
01-06-2010,14513
...
SQL Server doesn't support COUNT(DISTINCT ... ) OVER () or a numeric value (30 PRECEDING) in conjunction with RANGE
I wouldn't bother trying to coerce window functions into doing this. Because of the COUNT(DISTINCT UserID) requirement it is always going to have to re-examine the entire 30 day window for each date.
You can create a calendar table with a row for each date and use
SELECT C.Date,
NumberActiveUsersInPrevious30Days
FROM Calendar C
CROSS APPLY (SELECT COUNT(DISTINCT UserID)
FROM UserActivity
WHERE ActivityDateTime >= DATEADD(DAY, -30, C.[Date])
AND ActivityDateTime < C.[Date]) CA(NumberActiveUsersInPrevious30Days)
WHERE C.Date BETWEEN '2010-01-01' AND '2010-01-06'
Option 1: For (while) loop though each day and select 30 days backward for each (obviously quite slow).
Option 2: A separate table with a row for each day and join on the original table (again quite slow).
Option 3: Recursive CTEs or stored procs (still not doing much better).
Option 4: For (while) loop in combination with cursors (efficient, but requires some advanced SQL knowledge). With this solution you will step through each day and each row in order and keep track of the average (you'll need some sort of wrap-around array to know what value to subtract when a day moves out of range).
Option 5: Option 3 in a general-purpose / scripting programming language (C++ / Java / PHP) (easy to do with basic knowledge of one of those languages, efficient).
Some related questions.

Select rows whose IDs are not found in another table under certain constraints

The practical problem I'm solving is to display a list of items that have been updated recently that the user has not viewed recently.
I'm trying to return a table containing items that are not containing in an item views table for a given user (let's say for this case user number 1). I've come up with:
SELECT * FROM items i
WHERE i.updated_at > date_sub(curdate(), interval 10 day)
AND i.id NOT IN (
SELECT item_id FROM item_views v
WHERE i.created_at > date_sub(curdate(), interval 10 day)
AND i.user_id = 1
)
This seems to work fine (is it even the best way to do it?). However, I run into issues when considering an item that was viewed 8 days ago and updated 3 days ago. Such an item is clearly new, but it wouldn't show up under this query. How should I approach adding this restriction?
If you have the updated_at column in your view you could always add a line to check to make sure the updated date is not within your timeline. Better yet you could check to make sure your updated date is greater than your last viewed date.
This is not optimal solution. But fast anwser replace the AND with OR should work.

Selecting records from the past three months

I have 2 tables from which i need to run a query to display number of views a user had in the last 3 months from now.
So far I have come up with: all the field types are correct.
SELECT dbo_LU_USER.USERNAME
, Count(*) AS No_of_Sessions
FROM dbo_SDB_SESSION
INNER JOIN dbo_LU_USER
ON dbo_SDB_SESSION.FK_USERID = dbo_LU_USER.PK_USERID
WHERE (((DateDiff("m",[dbo_SDB_SESSION].[SESSIONSTART],Now()))=0
Or (DateDiff("m",[dbo_SDB_SESSION].[SESSIONSTART],Now()))=1
Or (DateDiff("m",[dbo_SDB_SESSION].[SESSIONSTART],Now()))=2))
GROUP BY dbo_LU_USER.USERNAME;
Basically, the code above display a list of all records within the past 3 months; however, it starts from the 1st day of the month and ends on the current date, but I need it to start 3 months prior to today's date.
Also to let you know this is SQL View in MS Access 2007 code.
Thanks in advance
Depending on how "strictly" you define your 3 months rule, you could make things a lot easier and probably efficient, by trying this:
SELECT dbo_LU_USER.USERNAME, Count(*) AS No_of_Sessions
FROM dbo_SDB_SESSION
INNER JOIN dbo_LU_USER
ON dbo_SDB_SESSION.FK_USERID = dbo_LU_USER.PK_USERID
WHERE [dbo_SDB_SESSION].[SESSIONSTART] between now() and DateAdd("d",-90,now())
GROUP BY dbo_LU_USER.USERNAME;
(Please understand that my MS SQL is a bit rusty, and can't test this at the moment: the idea is to make the query scan all record whose date is between "TODAY" and "TODAY-90 days").