Combine Metric and Dimension In Formula (Datastudio) - sql

I am trying to figure out how to create a column where...
clicks * (CASE
When Date <= "Jan 1, 2020" then 5
when Date >= "Jan 2, 2020" then 10
end)
But the error I am getting is this:
Sorry, calculated fields can't mix metrics (aggregated values) and
dimensions (non-aggregated values). Please check the aggregation types
of the fields used in this formula
Date is the dimension and clicks are the metric.
What the result should look like:
DATE ----- CLICKS --------- RESULT
Jan 1, 2020 100 500
Jan 1, 2020 40 200
Jan 1, 2020 10 50
Jan 2, 2020 30 300
Jan 1, 2020 90 900
Is there a way to change Date into a Metric, or is there another way to approach this problem?

I think the way the case statement is written is fine. You may need to check the data type for the Date dimension, and it should be in the "Date" format so that data studio knows to treat that data as a Date and then write the date in the case statement in the same format as well.

If you wrap the CASE inside a MAX you'll get back a number and you'll avoid the error.
clicks * MAX(
(CASE
WHEN Date <= "Jan 1, 2020" then 5
WHEN Date >= "Jan 2, 2020" then 10
END))

clicks * MAX(
(CASE
WHEN Date <= "Aug 15, 2021" then 2
WHEN Date > "Aug 15, 2021" then 4
END))
This worked!

Related

Find and sort all the data(dates) after a certain date by month/day and not year in SQLite

I wanna order the data in an sqlite3 database by date. (Day and Month to be precise)
I have a table,
the data in the table are in the format YYYY-MM-DD
2003-02-20, 2005-07-16, 2008-11-18, 1998-01-02, 1996-08-27
Here, I wanna find all the data after a certain date(Current date- 'now') and in order.
The data is birthdays, so the order should be just based off of Month and Day and shouldn't care about the year.
For example, the data here is
Feb 20, Jul 16, Nov 18, Jan 1, Aug 27
current day= July 28
I want the output to look like
Aug 27, Nov 18, Jan 1, Feb 20, Jul 16
I've looked through many examples and documentations and tried some methods
SELECT * FROM table WHERE birthdays>date('now')
*birthdays are the column where dates are stored*
This gives all the data after ('now') as an output, but it orders it by year as well. Hence, the output will be none since none of the years are greater than current year. I wanna take the year out of the equation and just order it by Month and Day.
How can I do it?
You don't need a WHERE clause because all rows of the table should be returned.
What you want is a proper ORDER BY clause:
SELECT *
FROM tablename
ORDER BY strftime('%m-%d', birthdays) > strftime('%m-%d', 'now') DESC,
strftime('%m-%d', birthdays);
See the demo.
According to the sample data and the expected output you posted, you want to find all birthdays that will occur this year after the date of today. You may use the strftime function to extract month and day as the following:
Select user_id, DOB
From your_table
Where strftime('%m-%d',DOB) > strftime('%m-%d',date())
Order By strftime('%m-%d',DOB)
See a demo from db-fiddle.
you can select the dates, by taking he day of birth, adding the current year ( or the next one if it is smalerer tan the current date)and then selecting the dates that are bigger than the current date limiting 10
SELECT user_id, DOB
FROM your_table
ORDER BY
CASE WHEN date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB)) > DATE() then date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB))
ELSE date(strftime('%Y', date('now','+1 years')) || strftime('-%m-%d', DOB)) END
LIMIT 10;
user_id DOB
5 1996-08-27
10 1996-08-27
15 1996-09-27
13 2008-10-18
3 2008-11-18
8 2008-11-18
4 1998-01-02
9 1998-01-02
14 1998-01-02
1 2003-01-31
db<>fiddle here

Querying for price of a product within a date range

I have to find the average price of iPhone Xs from this table within 1 August 2021 and 31 August 2021.
So the records that I have narrowed down are 8, 9, 11 and 12.
However records 8 and 9's StartDateTime and EndDateTime are outside of 1st and 31st August 2021, but still run through August 2021.
So far, I am only able to query for records 11 and 12.
Which is more straightforward:
SELECT *
FROM dbo.PriceHistory
WHERE
PName = 'iPhone Xs'
AND StartDateTime BETWEEN '2021-08-01 00:00:00.000' AND '2021-08-31 00:00:00.000';
How should I query so that I can get records 8 and 9 as well?
Based on the desired behaviour you've described, you probably want to check if the start date is before September 1, and the end date is after August 1. This will get all items whose date ranges overlap with August.
So:
SELECT *
FROM dbo.PriceHistory
WHERE
PName = 'iPhone Xs'
AND StartDateTime < '2021-09-01 00:00:00.000'
AND EndDateTime >= '2021-08-01 00:00:00.000';
(Note that the upper endpoint should be September 1 to ensure we include the last day of August.)

How do you extract the date format "Month_name date, year" into separate columns of date, month and year in Pandas? For eg. "August 30, 2019"

I've seen extractions of date, month and year from data format: "DD-MM-YYYY" and the like. (Where the month is numbered rather than named)
However, I have a dataset which has date values in the format: "Month_name date, year".
Eg. "August 30, 2019".
Assume that your DataFrame contains TxtDate column, with
date strings:
TxtDate
0 August 30, 2019
1 May 12, 2020
2 February 16, 2020
The first step is to convert the source column to datetime type and save it
in a new column:
df['Date'] = pd.to_datetime(df.TxtDate)
This function is so "clever" that you can do even without explicit
format specification.
Then extract partilular date components (and save them in respective
columns):
df['Year'] = df.Date.dt.year
df['Month'] = df.Date.dt.month
df['Day'] = df.Date.dt.day
And the last step is to drop Date column (you didn't write
that you need the whole date):
df.drop(columns='Date', inplace=True)
The result is:
TxtDate Year Month Day
0 August 30, 2019 2019 8 30
1 May 12, 2020 2020 5 12
2 February 16, 2020 2020 2 16
Maybe you should also drop TxtDate column (your choice).

SQL to Count status text and change some of those status texts (and their count) based on a date

Spent a while looking for this but did not quite find a solution. The problem: get counts for the status value in one column. Pretty simple so far, how ever I also want to change/ignore some of them when the DueDate (and it can be null) is past due based on current date and NOT complete. Also include empty strings for the status. Example Data (forgive the date show as text...assume it is a SQL date type - just wanted to make this more readable):
Current Date Apr : April 4, 2016
Data In DB Table DispatchStatus
Status Due Date
=======================================
Complete Mar 1, 2015 <-- would not be Late since Complete
Complete null
Complete July 12, 2016
Complete July 16, 2016
Started Mar 3, 2017
Started null
Started Feb 9, 2015 <-- Late
OnDevice June, 2016
OnDevice Dec 3, 2015 <-- Late
Dispatched Nov 16, 2015 <-- Late
Dispatched null
Dispatched Nov 20, 2016
Nov 15, 2017
null
Jan 15, 2016 <-- Late
The query should return:
Status Count
=========================
Complete 4
Started 2
OnDevice 1
2
Dispatched 2
Late 4
Thanks!
Use a CASE expression together with COUNT:
DECLARE #currentDate DATE = '20160404'
SELECT
Status =
CASE
WHEN DueDate <= #currentDate AND ISNULL(Status, '') <> 'Complete' THEN 'Late'
ELSE Status
END,
COUNT(*)
FROM DispatchStatus
GROUP BY
CASE
WHEN DueDate <= #currentDate AND ISNULL(Status, '') <> 'Complete' THEN 'Late'
ELSE Status
END
I think your sample current date should be Apr 4, 2016 based on your sample output.

Code erases previous month record while updating current month record

Using 11gR2, windows 7 client machine. I need to update the table missing_volume (below), where I need to calculate the estimated_missing column. The calculation of estimated_missing column for current month needs previous month numbers (as commented inside the code below). I want the output like the first table. Notice the records start from January, hence estimated_missing for January can't be calculated, but for the the rest of the months it can be done by simply changing 'yr' and 'mnth' (commented inside the code towards the end).
yr mnth location volume actual_missing expected_missing estimated_missing
2013 January loc1 48037 24 57
2013 February loc1 47960 3660 53 24
2013 March loc1 55007 78 57 28
2013 April loc1 54345 72 58 77
The code:
UPDATE missing_volume g
SET
g.estimated_missing =
(
SELECT
CASE
-- If the previous month actual_missing number is less than 2 times than that of the previous month expected_missing number,
-- then for current month:
-- estimated_missing = previous_month(actual_missing/volume)*current_month(volume)
--
-- Else, for current month:
-- estimated_missing = previous_month(estimated_missing/volume)*current_month(volume)
WHEN (NVL(p.actual_missing, 0)/NVL(p.expected_missing, 1)) <= 2.0
THEN ROUND(NVL(p.actual_missing, 0)*( NVL(g.volume, 0)/NVL(p.volume, 1) ), 0)
ELSE
ROUND(NVL(p.estimated_missing, 0)*( NVL(g.volume, 0)/NVL(p.volume, 1) ), 0)
END
FROM
(
SELECT
yr,
mnth,
loc_cd,
volume,
actual_missing,
expected_missing,
estimated_missing
FROM missing_volume
WHERE yr = TRIM(TO_CHAR(ADD_MONTHS(SYSDATE, -2), 'YYYY')) -- For February it is -4, for March it is -3, for April it is -2
AND UPPER(mnth) = UPPER(TRIM(TO_CHAR(ADD_MONTHS(SYSDATE, -2), 'Month'))) -- For February it is -4, for March it is -3, for April it is -2
)p
WHERE g.yr = TRIM(TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'YYYY')) -- For February it is -3, for March it is -2, for April it is -1
AND UPPER(g.mnth) = UPPER(TRIM(TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'Month'))) -- For February it is -3, for March it is -2, for April it is -1
AND g.volume IS NOT NULL
AND TRIM(p.location) = TRIM(g.location)
);
The code does calculate correct number for 'estimated_missing' as I run the code for each month, but the problem is while updating the current month it also erases the record for previous month. E.g. as can be seen below, after I updated April the column only has the record for April, previous month record is gone, similarly updating March removed February, etc. I can't understand why it's happening!! Here is the output I get:
yr mnth location volume actual_missing expected_missing estimated_missing
2013 January loc1 48037 24 57
2013 February loc1 47960 3660 53
2013 March loc1 55007 78 57
2013 April loc1 54345 72 58 77
Will appreciate if any body can explain why it's happening (I mean where is the flaw in the code) and how to get the desired output (first table).
Thanks
You need to specify a where clause for your statement.
At the moment that WHERE clause is inside the braces. Your statement basically is:
UPDATE missing_volume g
SET
g.estimated_missing =
( [...]
); -- no where clause here
What you need is this:
UPDATE missing_volume g
SET
g.estimated_missing =
( [...]
)
WHERE g.yr = TRIM(TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'YYYY'));
Haven't tested it myself but this should only update the row for the current month.