I had a long break from SQL and am a bit rusty. Let's say I have 3 columns in my table: username, value_of_sale, date.
I need a select statement to show me 4 columns based on this table:
username
sum of value_of_sales (where date = today)
sum of value_of_sales (where date = today-1)
sum of value_of_sales (where date = today-2)
I am using db2.
Use SUM and GROUP BY.
SELECT username,
(CASE WHEN date = CURRENT_DATE THEN value_of_sale ELSE 0 END) AS SUMtoday,
(CASE WHEN date = DAYOFYEAR(CURRENT_DATE) - 1 ) THEN value_of_sale ELSE 0 END) AS SUMtoday-1,
(CASE WHEN date = DAYOFYEAR(CURRENT_DATE) - 2 ) THEN value_of_sale ELSE 0 END) AS SUMtoday-2
FROM yourtable
GROUP BY username
Without trying to merge all three of those together, it's very simple to do them individually:
Today:
SELECT username, SUM(value_of_sale) FROM `tableName` WHERE DATE(`date`) = CURDATE() GROUP BY username
Yesterday:
SELECT username, SUM(value_of_sale) FROM `tableName` WHERE DATE(`date`) = DATE_ADD(CURDATE(), INTERVAL -1 DAY) GROUP BY username
Two Days Ago:
SELECT username, SUM(value_of_sale) FROM `tableName` WHERE DATE(`date`) = DATE_ADD(CURDATE(), INTERVAL -2 DAY) GROUP BY username
DATE('date') takes the date portion of the timestamp. If your data is just listed in dates, then you can just compare 'date' to today's date.
CURDATE() gets today's date in the server.
DATE_ADD() is used to add or subtract days.
I have three fields in my table id,sale_amount,created_at(Sales Date)
SELECT (SELECT sum(sale_amount) FROM `sales` WHERE created_at =
CURDATE()) AS todaySale,(SELECT sum(sale_amount) FROM `sales` WHERE
created_at = CURDATE() -1) AS YesterdaySale,(SELECT sum(sale_amount)
FROM `sales` WHERE created_at = CURDATE() - 2) AS Last2DaysSale
This will help you for sure. Thank You
Probably not the most efficient method, but ...
select username,
sum(case when date = today then value_of_sales else 0 end) [Today],
sum(case when date = today-1 then value_of_sales else 0 end) [Yesterday],
sum(case when date = today-2 then value_of_sales else 0 end) [TheDayBefore]
from table
group by username
Related
The following table is given:
Columns
Deal start date
Deal end date
Amount
There is a table:
Start Date
End Date
Amount
01.01.2020
01.01.2021
1
15.04.2020
15.04.2021
3
It is required to write a query that returns, for two dates, the total balances of active deals on these dates.
It is required to display balances on date 1 = 02.05.2020 and date 2 = 02.02.2021
I know how to get them one by one
SELECT SUM(Amount)
FROM Table
WHERE 02.05.2020 >= End Date
Or
SELECT SUM(Amount)
FROM Table
WHERE 02.05.2020 >= End Date OR 02.02.2021 >= End Date
But I have no idea how to create a separate table for dates:
date 1 || amount 1
date 2 || amount 2
Can you give me some advice or direction for a solution?
You could use conditional aggregation or filtered sum function as the following:
SELECT
SUM(CASE WHEN '02.05.2020' >= End_Date THEN Amount ELSE 0 END) AS Date1,
SUM(CASE WHEN '02.05.2020' >= End_Date OR '02.02.2021' >= End_Date THEN Amount ELSE 0 END) AS Date2
FROM table_name
Or:
SELECT
SUM(Amount) FILTER (WHERE '02.05.2020' >= End_Date) AS Date1,
SUM(Amount) FILTER (WHERE '02.05.2020' >= End_Date OR '02.02.2021' >= End_Date) AS Date2
FROM table_name
See a demo.
I am trying to build a query to count user reactivations per month, where "reactivation" is defined as (for e.g. March 2021):
Sent activity during, or before, January 2021
Did not send activity during February 2021
Sent activity during March 2021
(so 1 or more full calendar months of no activity as the threshold for inactive).
The source table F_ACTIVITY is a per-user per-day time series with columns:
dt (date), user_id, is_active (boolean).
The desired outcome is a table showing:
month, reactivations_this_month
The closest I can get is a count of reactivations in the current month, or something relative to the current date with more case statements (e.g. repeating for current month -2):
SELECT
COUNT(*) AS reactivations_this_month
FROM
(SELECT
* FROM
(SELECT
user_id,
SUM(current_month_active) AS cma,
SUM(last_month_active) AS lma,
SUM(historical_active) AS h_a
FROM
(SELECT
user_id,
dt,
CASE WHEN DATE_TRUNC(MONTH, DT) = ADD_MONTHS(DATE_TRUNC(MONTH, CURRENT_TIMESTAMP), 0) THEN 1 ELSE 0 END AS current_month_active,
CASE WHEN DATE_TRUNC(MONTH, DT) = ADD_MONTHS(DATE_TRUNC(MONTH, CURRENT_TIMESTAMP), -1) THEN 1 ELSE 0 END AS last_month_active,
CASE WHEN DATE_TRUNC(MONTH, DT) < ADD_MONTHS(DATE_TRUNC(MONTH, CURRENT_TIMESTAMP), -1) THEN 1 ELSE 0 END AS historical_active
FROM F_ACTIVITY
WHERE is_active = 1
) AS x
GROUP BY user_id) AS y
WHERE cma > 0
AND lma = 0
AND h_a > 0) AS z
Any help transforming this into a rolling monthly query greatly appreciated - thanks all!
Final note: I'm trying this in Snowflake, so the dialect is SnowSQL
First summarize by month and user, then use lag():
SELECT yyyymm,
SUM(CASE WHEN prev_yyyymm < yyyymm - INTERVAL '1 month' THEN 1 ELSE 0 END) as num_reactivations
FROM (SELECT user_id, DATE_TRUNC(MONTH, DT) as yyyymm,
LAG(DATE_TRUNC(MONTH, DT)) OVER (PARTITION BY user_id ORDER BY DATE_TRUNC(MONTH, DT)) as prev_yyyymm
FROM F_ACTIVITY
WHERE is_active = 1
GROUP BY user_id, DATE_TRUNC(MONTH, DT)
) um
GROUP BY yyyymm;
With the query, I basically want to compare avg_clicks at different time periods and set a filter according to the avg_clicks.
The below query gives us avg_clicks for each shop in January 2020. But I want to see the avg_clicks that is higher than 0 in January 2020.
Question 1: When I add the where avg_clicks > 0 in the query, I am getting the following error: Column 'avg_clicks' cannot be resolved. Where to put the filter?
SELECT AVG(a.clicks) AS avg_clicks,
a.shop_id,
b.shop_name
FROM
(SELECT SUM(clicks_on) AS clicks,
shop_id,
date
FROM X
WHERE site = ‘com’
AND date >= CAST('2020-01-01' AS date)
AND date <= CAST('2020-01-31' AS date)
GROUP BY shop_id, date) as a
JOIN Y as b
ON a.shop_id = b.shop_id
GROUP BY a.shop_id, b.shop_name
Question 2: As I wrote, I want to compare two different times. And now, I want to see avg_clicks that is 0 in February 2020.
As a result, the desired output will show me the list of shops that had more than 0 clicks in January, but 0 clicks in February.
Hope I could explain my question. Thanks in advance.
For your Question 1 try to use having clause. Read execution order of SQL statement which gives you a better idea why are you getting avg_clicks() error.
SELECT AVG(a.clicks) AS avg_clicks,
a.shop_id,
b.shop_name
FROM
(SELECT SUM(clicks_on) AS clicks,
shop_id,
date
FROM X
WHERE site = ‘com’
AND date >= '2020-01-01'
AND date <= '2020-01-31'
GROUP BY shop_id, date) as a
JOIN Y as b
ON a.shop_id = b.shop_id
GROUP BY a.shop_id, b.shop_name
HAVING AVG(a.clicks) > 0
For your Question 2, you can do something like this
SELECT
shop_id,
b.shop_name,
jan_avg_clicks,
feb_avg_clicks
FROM
(
SELECT
AVG(clicks) AS jan_avg_clicks,
shop_id
FROM
(
SELECT
SUM(clicks_on) AS clicks,
shop_id,
date
FROM X
WHERE site = ‘com’
AND date >= '2020-01-01'
AND date <= '2020-01-31'
GROUP BY
shop_id,
date
) as a
GROUP BY
shop_id
HAVING AVG(clicks) > 0
) jan
join
(
SELECT
AVG(clicks) AS feb_avg_clicks,
shop_id
FROM
(
SELECT
SUM(clicks_on) AS clicks,
shop_id,
date
FROM X
WHERE site = ‘com’
AND date >= '2020-02-01'
AND date < '2020-03-01'
GROUP BY
shop_id,
date
) as a
GROUP BY
shop_id
HAVING AVG(clicks) = 0
) feb
on jan.shop_id = feb.shop_id
join Y as b
on jan.shop_id = b.shop_id
Start with conditional aggregation:
SELECT shop_id,
SUM(CASE WHEN DATE_TRUNC('month', date) = '2020-01-01' THEN clicks_on END) / COUNT(DISTINCT date) as avg_clicks_jan,
SUM(CASE WHEN DATE_TRUNC('month', date) = '2020-02-01' THEN clicks_on END) / COUNT(DISTINCT date) as avg_clicks_feb
FROM X
WHERE site = 'com' AND
date >= '2020-01-01' AND
date < '2020-03-01'
GROUP BY shop_id;
I'm not sure what comparison you want to make. But if you want to filter based on the aggregated values, use a HAVING clause.
My data has an ID, date, and points_earned field. Each row represents the points earned by the ID for that date.
I want to create something similar to this:
ID | Points_Earned_January | Points_Earned_February | Points_Earned_March
The result should be GROUP BY ID. Points_Earned_January should give a SUM of all the points_earned that fall in January for that ID.
How can I do this?
You can use conditional aggregation:
select id,
(case when date >= '2020-02-01' and date < '2020-03-01' then points else 0 end) as points_feb,
(case when date >= '2020-03-01' and date < '2020-04-01' then points else 0 end) as points_mar
from t
group by id;
I have a usage table with user_id and login time. I want to get the number of users who logged in at least once a day. I also need to get the number of users who logged in at least once a week.
Any idea how can I go about it with a redshift query?
Here is the schema:
user_id: BigInt
event_time: Datetime
Example results:
No. of users who logged in at least once every day: 20
No. of users who logged in at least once week: 5
Try this:
/* Days range from date1 to date2 */
WITH day_range AS (
SELECT current_date + i AS day
FROM generate_series(DATE [$from_date] - current_date, DATE [$to_date] - current_date) i
)
/* Users logged at least once a day */
SELECT DISTINCT user_id
FROM user_event
WHERE NOT EXISTS
(SELECT user_id
FROM day_range LEFT JOIN user_event ON day_range.day = user_event.event_time::date
WHERE user_id IS NULL)
For users who has been logged at least once a week it should be more complicated but something similar.
This is a pseudo SQL, should give you what you are looking for.
SELECT Sum(CASE
WHEN daycount = datediff('day', '{start_date}', '{end_date}')
THEN 1
ELSE 0
END) AS visited_every_day
,Sum(CASE
WHEN weekcount = datediff('week', '{start_date}', '{end_date}')
THEN 1
ELSE 0
END) AS visited_every_week
FROM (
SELECT user_id
,Count(DISTINCT to_char(event_time, 'YYYYMMDD')) AS daycount
,Count(DISTINCT to_char(event_time, 'WW')) AS weekcount
FROM user_event ue
WHERE Event_time BETWEEN '{start_date}'
AND '{end_date}'
GROUP BY user_id
) stage