Create or add random number to fulfill some condition - google-bigquery

I have data like this..
month_date location sales
2022-01-01 Asia 150
2022-01-01 Europe 250
2022-02-01 Asia 100
2022-02-01 Europe 100
and breakdown by day_date
day_date location sales
2022-01-01 Asia 12
2022-01-02 Asia 10
2022-01-03 Asia 15
2022-01-04 Asia 19
2022-01-05 Asia 15
2022-01-06 Asia 11
....
2022-01-31 Asia 2
total: Asia 132
but when I compare sales between month_date=150 and day_date=132 I still have minus 18.
is it possible to add random data which contain minus 18 but breakdown by day_date?
like below
day_date location sales
2022-01-01 Asia 13
2022-01-02 Asia 11
2022-01-03 Asia 16
2022-01-04 Asia 20
2022-01-05 Asia 16
2022-01-06 Asia 12
....
2022-01-31 Asia 2
total: Asia 150

You might consider below. (diff number, 18 in this case, will be added by one starting from 1st day of month.)
SELECT day_date, location,
sales + DIV(diff, days) + IF(EXTRACT(DAY FROM day_date) <= MOD(diff, days), 1, 0) AS sales
FROM (
SELECT d.*,
m.sales - SUM(d.sales) OVER w AS diff,
DATE_DIFF(LAST_DAY(month_date), month_date, DAY) AS days
FROM day_table d
LEFT JOIN month_table m
ON DATE_TRUNC(d.day_date, MONTH) = m.month_date AND d.location = m.location
WINDOW w AS (PARTITION BY DATE_TRUNC(day_date, MONTH), d.location)
);
Query results

Related

Get the amount in two days

I'm trying to write a query that will return the amount of sales given the previous day. I am doing a test task for an internship device but have not done this before.
Source table:
saledate
salesum
2022-01-01
100
2022-01-02
150
2022-01-03
200
2022-01-05
100
Estimated result:
saledate
salesum
2022-01-01
100
2022-01-02
250
2022-01-03
350
2022-01-05
300
My query:
SELECT t1.saledate, t1.salesum=t1.salesum+t2.salesum
FROM sales t1
INNER JOIN (
SELECT saledate, salesum FROM sales
) t2
ON t1.saledate=t2.saledate;
My result:
saledate
salesum
2022-01-01
f
2022-01-02
f
2022-01-03
f
2022-01-05
f
select saledate
,salesum + coalesce(lag(salesum) over(order by saledate),0) as salesum
from t
saledate
salesum
2022-01-01
100
2022-01-02
250
2022-01-03
350
2022-01-05
300
Fiddle

Calculate Average for Amount for certain date range in a year based on month

I have a table like below :
ID
Amount
Date
1
500
2022-01-03
1
200
2022-01-04
1
500
2022-01-05
1
340
2022-01-06
1
500
2022-01-25
1
500
2022-01-26
1
567
2022-01-27
1
500
2022-01-28
1
598
2022-01-31
1
500
2022-02-01
1
787
2022-02-02
1
500
2022-02-03
1
5340
2022-02-04
PROBLEM :-
So I have to calculate average of column where StartDate = 03/01/2022 (3rd Jan 2022) and for each month it would be like for January Average of Amount from StartDate to 25th Jan, then for Feb Startdate to 22nd Feb, so this date logic is also there
SET #Last = (SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, #Date)
WHEN 'Sunday' THEN -6
When 'Saturday' THEN -5
ELSE -7 END, DATEDIFF(DAY, 0, #Date)))
RETURN #Last
ID
Amount
Date
Last
1
500
2022-01-03
2022-01-25
1
500
2022-01-04
2022-01-25
1
340
2022-01-05
2022-01-25
1
500
2022-01-06
2022-01-25
1
567
2022-01-25
2022-01-25
1
500
2022-01-26
2022-01-25
1
500
2022-01-27
2022-01-25
1
40
2022-01-28
2022-01-25
1
500
2022-01-31
2022-01-25
1
589
2022-02-01
2022-02-22
1
540
2022-02-02
2022-02-22
1
500
2022-02-03
2022-02-22
1
5340
2022-02-04
2022-02-22
Like the above table..
Now if I calculate Avg(Amount), from 3rd jan to 25th Jan for Jan and 3rd Jan to 22nd Feb and so on.. It's not giving correct average, like it is calculating the rest of the days amount also. Also grouping by is grouping month wise not as where clause
Select Avg(Amount) from Table
where Date BETWEEN #StartDate AND Last
StartDate is fixed # 3rd Jan.
This is not giving the correct Avg. Any other way I could get the required data?

SQL SSMS merge IDs into row grouping by dates

I have two tables:
Main table
ID
Date
Device
252708
2022-01-01
Phone
252708
2022-01-01
Email
252252
2022-01-02
Phone
252252
2022-01-02
Phone
252252
2022-01-02
Phone
253022
2022-01-06
Phone
253022
2022-01-06
Phone
253228
2022-01-06
Email
253228
2022-01-06
Email
252708
2022-01-06
Phone
256703
2022-01-09
Phone
Date table
Date
Week
2022-01-01
WK 17
2022-01-02
WK 18
2022-01-03
WK 18
2022-01-04
WK 18
2022-01-05
WK 18
2022-01-06
WK 18
2022-01-07
WK 18
2022-01-08
WK 18
2022-01-09
WK 19
2022-01-10
WK 19
2022-01-11
WK 19
I want to merge the IDs into rows, grouping by Wk (using my date table)
ID
Date
Device_1
Wk
252708
2022-01-01
Phone, Email
WK17
252252
2022-01-02
Phone, Phone, Phone
WK18
253022
2022-01-06
Phone, Phone
WK18
253228
2022-01-06
Email, Email
WK18
252708
2022-01-06
Phone
WK18
256703
2022-01-09
Phone
WK19
I know I need the string_agg function to merge the devices into rows, however, I'm not sure how to separate by week. Thanks in advance
You can always use "FOR XML" instead of STRING_AGG. It would be something like this:
select
distinct(dev.ID)
,dev.Date
,(
select
Device + ',' as [text()]
FROM MainTable a
JOIN DateTable b on a.Date = b.Date
Where dev.ID = a.ID and b.Week = cal.Week
FOR XML PATH ('')
) as Device_1
,cal.Week
FROM MainTable dev
JOIN DateTable cal on dev.Date = cal.Date
Order By Week

CASE in WHERE Clause in Snowflake

I am trying to do a case statement within the where clause in snowflake but I’m not quite sure how should I go about doing it.
What I’m trying to do is, if my current month is Jan, then the where clause for date is between start of previous year and today. If not, the where clause for date would be between start of current year and today.
WHERE
CASE MONTH(CURRENT_DATE()) = 1 THEN DATE BETWEEN DATE_TRUNC(‘YEAR’, DATEADD(YEAR, -1, CURRENT_DATE())) AND CURRENT_DATE()
CASE MONTH(CURRENT_DATE()) != 1 THEN DATE BETWEEN DATE_TRUNC(‘YEAR’, CURRENT_DATE()) AND CURRENT_DATE()
END
Appreciate any help on this!
Use a CASE expression that returns -1 if the current month is January or 0 for any other month, so that you can get with DATEADD() a date of the previous or the current year to use in DATE_TRUNC():
WHERE DATE BETWEEN
DATE_TRUNC('YEAR', DATEADD(YEAR, CASE WHEN MONTH(CURRENT_DATE()) = 1 THEN -1 ELSE 0 END, CURRENT_DATE()))
AND
CURRENT_DATE()
I suspect that you don't even need to use CASE here:
WHERE
(MONTH(CURRENT_DATE()) = 1 AND
DATE BETWEEN DATE_TRUNC(‘YEAR’, DATEADD(YEAR, -1, CURRENT_DATE())) AND
CURRENT_DATE()) OR
(MONTH(CURRENT_DATE()) != 1 AND
DATE BETWEEN DATE_TRUNC(‘YEAR’, CURRENT_DATE()) AND CURRENT_DATE())
So the other answers are quite good, but... the answer can be even simpler
Making a little table to brake down what is happening.
select
row_number() over (order by null) - 1 as rn,
dateadd('day', rn * 5, date_trunc('year',current_date())) as pretend_current_date,
DATEADD(YEAR, -1, pretend_current_date) as pcd_sub1,
month(pretend_current_date) as pcd_month,
DATE_TRUNC(year, iff(pcd_month = 1, pcd_sub1, pretend_current_date)) as _from,
pretend_current_date as _to
from table(generator(ROWCOUNT => 30))
order by rn;
this shows:
RN
PRETEND_CURRENT_DATE
PCD_SUB1
PCD_MONTH
_FROM
_TO
0
2022-01-01
2021-01-01
1
2021-01-01
2022-01-01
1
2022-01-06
2021-01-06
1
2021-01-01
2022-01-06
2
2022-01-11
2021-01-11
1
2021-01-01
2022-01-11
3
2022-01-16
2021-01-16
1
2021-01-01
2022-01-16
4
2022-01-21
2021-01-21
1
2021-01-01
2022-01-21
5
2022-01-26
2021-01-26
1
2021-01-01
2022-01-26
6
2022-01-31
2021-01-31
1
2021-01-01
2022-01-31
7
2022-02-05
2021-02-05
2
2022-01-01
2022-02-05
8
2022-02-10
2021-02-10
2
2022-01-01
2022-02-10
9
2022-02-15
2021-02-15
2
2022-01-01
2022-02-15
10
2022-02-20
2021-02-20
2
2022-01-01
2022-02-20
11
2022-02-25
2021-02-25
2
2022-01-01
2022-02-25
12
2022-03-02
2021-03-02
3
2022-01-01
2022-03-02
13
2022-03-07
2021-03-07
3
2022-01-01
2022-03-07
14
2022-03-12
2021-03-12
3
2022-01-01
2022-03-12
15
2022-03-17
2021-03-17
3
2022-01-01
2022-03-17
16
2022-03-22
2021-03-22
3
2022-01-01
2022-03-22
17
2022-03-27
2021-03-27
3
2022-01-01
2022-03-27
18
2022-04-01
2021-04-01
4
2022-01-01
2022-04-01
19
2022-04-06
2021-04-06
4
2022-01-01
2022-04-06
20
2022-04-11
2021-04-11
4
2022-01-01
2022-04-11
21
2022-04-16
2021-04-16
4
2022-01-01
2022-04-16
22
2022-04-21
2021-04-21
4
2022-01-01
2022-04-21
23
2022-04-26
2021-04-26
4
2022-01-01
2022-04-26
24
2022-05-01
2021-05-01
5
2022-01-01
2022-05-01
25
2022-05-06
2021-05-06
5
2022-01-01
2022-05-06
26
2022-05-11
2021-05-11
5
2022-01-01
2022-05-11
27
2022-05-16
2021-05-16
5
2022-01-01
2022-05-16
28
2022-05-21
2021-05-21
5
2022-01-01
2022-05-21
29
2022-05-26
2021-05-26
5
2022-01-01
2022-05-26
Your logic is asking "is the current date in the month of January", at which point take the prior year, and then date truncate to the year, otherwise take the current date and truncate to the year. As the start of a BETWEEN test.
This is the same as getting the current date subtracting one month, and truncating this to year.
Thus there is no need for any IFF or CASE
WHERE date BETWEEN DATE_TRUNC(year, DATEADD(month,-1, CURRENT_DATE())) AND CURRENT_DATE()
and if you like to drop some paren's, CURRENT_DATE can be used if you leave it in upper case, thus it can even be smaller:
WHERE date BETWEEN DATE_TRUNC(year, DATEADD(month,-1, CURRENT_DATE)) AND CURRENT_DATE

Query Sales Group by week no and Month

I have to calculate sales based on WeekNo(Yearly) and Month.
Table1: Sales
ID SalDate Amount Region
1 2020-12-27 1000 USA
2 2020-12-28 1000 EU
3 2020-12-29 1000 AUS
4 2021-01-01 1000 USA
5 2021-01-02 1000 EU
6 2021-01-05 1000 AUS
7 2020-09-30 1000 EU
8 2020-10-01 1000 AUS
Select DateName(Month,SalDate)+' - '+Convert(Varchar(10),Year(SalDate)) Months,
'Week '+ Convert(Varchar(50), DATEPART(WEEK, SalDate)) As Weeks,
Sum(Amount) OrderValue
From [Sales]
Group By DateName(Month,SalDate)+' - '+Convert(Varchar(10),Year(SalDate)),
Convert(Varchar(50), DATEPART(WEEK, SalDate))
Months Weeks Total
January - 2021 Week 1 2000.00
January - 2021 Week 2 1000.00
December - 2020 Week 53 3000.00
October - 2020 Week 40 1000.00
September - 2020 Week 40 1000.00
But client want to merge Week1 Total with Week 53
And Week2 show as Week1.
And Week 40 Merge with Sep 2020.
I want result like below
Months Weeks Total
January - 2021 Week 1 1000.00
December - 2020 Week 53 5000.00 (2000+3000)
September - 2020 Week 40 2000.00 (1000+100)
Kindly help me to fix this problem.