Transposing quarters as row to column using BigQuery - google-bigquery

I have data that contains Quarters as rows.
Is it possible to convert 7 Quarters into columns using BigQuery?
My data :
Desired output :
Methods used by me :
Offset clause
Select Name,
SUM(CASE WHEN QuarterEnding ='Q1, 2020' THEN AT END) Q12020,
SUM(CASE WHEN QuarterEnding='Q2, 2020' THEN AT END) Q22020,
SUM(CASE WHEN QuarterEnding='Q3, 2020' THEN AT END) Q32020,
SUM(CASE WHEN QuarterEnding='Q4, 2020' THEN AT END) Q42020,
FROM `table1`
GROUP by 1;

As #Pi-R mentioned, example query in the documentation is very close to what you want but for your specific desired output, you might consider below.
SELECT * FROM (
SELECT * EXCEPT(City) FROM `table1`
) PIVOT (
SUM(`AT`) FOR TRANSLATE(QuarterEnding, ', ', '')
IN ('Q12020', 'Q22020', 'Q32020', 'Q42020',
'Q12021', 'Q22021', 'Q32021', 'Q42021')
);

You can look at pivot function of BigQuery https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#pivot_operator. There is the same use case as yours
First you have to rename quarter's name so they can be a field.
Q1, 2020 => Q12020
Then you can use
SELECT * FROM `table_name`
PIVOT(min(ID) FOR QuarterEnding IN ('Q12020', 'Q22020', 'Q32020', 'Q42020','Q12021', 'Q22021', 'Q32021', 'Q42021'))

Related

How do I change the query to just show one row SQL?

I am trying to compile a view of how many instances occur in each month. I have the below code, which gets me the answer, but also gives multiple rows. How do I limit the view to just one row, with each column being the amount of instances each month?
CREATE VIEW new_users_per_month AS
SELECT (
SELECT COUNT(id) AS January
FROM master_table
WHERE month(created_at)=1) AS January,
(
SELECT COUNT(id) AS February
FROM master_table
WHERE month(created_at)=2) AS February,
(
SELECT COUNT(id) AS March
FROM master_table
WHERE month(created_at)=3) AS March
FROM master_table;
Do conditional aggregation :
select count(case when month(created_at) = 1 then id end) as Jan,
count(case when month(created_at) = 2 then id end) as Feb,
count(case when month(created_at) = 3 then id end) as Mar
from master_table t;
Not properly tested, i will create dummy and test in a moment, but in support of my comment
select *
from
(
select
t.id,
month(t.created_at) as MTH_CRE
from master_table as t
) as q
pivot
(
count(id) for MTH_CRE in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) as pvt

T-SQL Using CTE to aggregate totals for matching and non-matching periods

Matched Sales are provided by the join, It's getting the unmatched that is eluding me.
CTE
With PriorSalesCTE
(
Item
Variant,
Sum(sales)
Date between 7/1/2020 and 7/5/2020
),
CurrentSalesCTE
(
Item
Variant,
Sum(sales)
Date between 7/1/2021 and 7/5/2021
)
Select
SUM(cs.Sales) ‘MatchedSales’
FROM PriorSalesCTE ps join CurrentSalesCTE ps
ON cs.Item = ps.Item
And cs.Variant = ps.Variant
Now I need the empty spaces on both sides
I need the sales for items sold in 2020 but not sold in 2021 – Lost Sales
Conversely, sales for 2021 that did not sell in 2020 – New Sales.
I tried adding these in the CTE as separate sections of the CTE, but the join doesn’t give me what I need.
Any suggestions? Is the CTE simply preventing me for getting everything and maybe add a UNION ALL query to get the unmatched values?
For your actual query, you could use a FULL JOIN, which will give you the results from either side also.
But I think there is another solution: you don't need to join separate queries for this, you can just use conditional aggregation
WITH SalesByItem AS (
SELECT
t.Item,
t.Variant
Sales2020 = SUM(CASE WHEN Date BETWEEN '20200701' and '20200705' THEN t.Sales END),
Sales2021 = SUM(CASE WHEN Date BETWEEN '20210701' and '20210705' THEN t.Sales END)
FROM YourTable t
WHERE (Date BETWEEN '20200701' and '20200705'
OR Date BETWEEN '20210701' and '20210705')
GROUP BY
t.Item,
t.Variant
)
SELECT
NewSales = SUM(CASE WHEN Sales2020 IS NULL THEN Sales2021 END),
MatchedSales = SUM(CASE WHEN Sales2020 IS NOT NULL AND Sales2021 IS NOT NULL THEN Sales2021 END),
LostSales = SUM(CASE WHEN Sales2021 IS NULL THEN Sales2020 END)
FROM SalesByItem s;

How to build logic to find the history of Red and Amber records with below example

with archer_summary_base as (select * from kri.archer_kri_latest_summary
where segment='All Segments' and Level_I_Risk!='' and metric_identifier in ('Mandatory') and (metric_results_status='Amber' or metric_results_status='Red' or metric_results_status is null) and
(month='January' or month='February' or month='March' or month='December' or month='November' or month='April' or month is null) AND (year=2021 or year=2020 or year is null)
and status='Active' and originated_source ='Archer'),
--select * from archer_summary_base
archer_summary_main as (select * from kri.archer_kri_latest_summary where metric_id in (select metric_id from archer_summary_base)
and (month='January' or month='February' or month='March' or month='December' or month='November' or month='April' or month is null)
AND (year=2021 or year=2020 or year is null) and segment='All Segments' and Level_I_Risk !='' and originated_source ='Archer' and
metric_identifier in ('Mandatory')),
breach_kri_report AS (select metric_id,
trim(Level_I_Risk) as Level_I_Risk,
trim(Metric_Name) as Metric_Name,
(case when format in ('Percentage') then concat(regexp_replace(regexp_replace(Green_threshold_min,'\\.0+$',''),'(\\d+\\.\\d+?)0+$','$1'),'%','-',regexp_replace(regexp_replace(Green_threshold_max,'\\.0+$',''),'(\\d+\\.\\d+?)0+$','$1'),'%')
when format in ('Monetary Amount') then concat('$',format_number(cast(Green_threshold_min as bigint),0),' -','$',format_number(cast(Green_threshold_max as bigint),0))
when format in ('Number') then concat(cast(Green_threshold_min as bigint),'-',cast(Green_threshold_max as bigint))
end) as Green_Threshold,
trim(PATH_TO_GREEN_INDICATOR) as P2G_Indicator,
concat(substring(Month,1,3), '-', substring(year,3,4)) as Month_Name,
(case when format in ('Percentage') then concat(cast(metric_value as bigint),'%')
when format in ('Monetary Amount') then concat('$',(format_number(cast(metric_value as bigint),0)))
when format in ('Number') then format_number(cast(metric_value as bigint),0) end) as DerivedValue_Avg
from archer_summary_main group by metric_id,Level_I_Risk,Metric_Name,Green_threshold_min,Green_threshold_max,PATH_TO_GREEN_INDICATOR,month,year,format,metric_value),
--Select * from breach_kri_report,
exsummary as (SELECT b.Level_I_Risk,
b.Metric_Name,
b.Green_Threshold,
b.P2G_Indicator,
case when Month_Name='Nov-20' then DerivedValue_Avg end as Nov_20,
case when Month_Name='Dec-20' then DerivedValue_Avg end as Dec_20,
case when Month_Name='Jan-21' then DerivedValue_Avg end as Jan_21,
case when Month_Name='Feb-21' then DerivedValue_Avg end as Feb_21,
case when Month_Name='Mar-21' then DerivedValue_Avg end as Mar_21,
case when Month_Name='Apr-21' then DerivedValue_Avg end as Apr_21
FROM breach_kri_report b)
select
t.Level_I_Risk,
t.Metric_Name,
t.Green_Threshold,
t.P2G_Indicator,
collect_list(Nov_20)[0] as Nov_20,
collect_list(Dec_20)[0] as Dec_20,
collect_list(Jan_21)[0] as Jan_21,
collect_list(Feb_21)[0] as Feb_21,
collect_list(Mar_21)[0] as Mar_21,
collect_list(Apr_21)[0] as Apr_21
from exsummary t
group by t.Level_I_Risk, t.Metric_Name, t.Green_Threshold, t.P2G_Indicator
Below results i am getting shown in screen shot
the 'Green' which are circled should not come when I run the query because I want to get history for Red and amber. I am ok to get the green records as part of the history but not in the beginning or in the latest months
Below is what I am trying to achieve
Here is an outline to a possible query:
Issue a subquery using a window function, partition by year and month, pick the lowest pk_key by sorting by year, month and pk_key ascending and select the first result for each partition.
Then use the results in combination with a where clause and a second constraint:
... where not(pk_key in (first_query.pk_key) and metric_results_status = 'GREEN')
Sorry, but I can't provide anything more specific, since the details you gave are not very clear on as to what your database structure in actuality looks like.
May God have mercy upon your soul!

How to use CASE WHEN in group by

I want to use group by for the table NRW_MONTH_DATA.
SELECT [OBJECT_ID]
,[YEAR_MONTH]
,[SELLING_AMOUNT]
,[DEFAULT_SELLING_DATA]
,[LOCK_SELLING_AMOUNT]
,[RGCB]
,[ICKZ]
,[YCKZ]
FROM [dbo].[NRW_MONTH_DATA]
IF LOCK_SELLING_AMOUNT is 0 then group by OBJECT_ID and calculate the sum of [RGCB],[ICKZ] and [YCKZ]
SELECT #SELLING_AMOUNT=(ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID
AND YEAR_MONTH >=#SELLING_CENSUS_START_YM
AND YEAR_MONTH <=#SELLING_CENSUS_END_YM
GROUP BY OBJECT_ID
Now I want to add a condition that if LOCK_SELLING_AMOUNT is 1 , I need to
SELECT #SELLING_AMOUNT=ISNULL(SUM(DEFAULT_SELLING_DATA),0)
ELSE use original result to calculate the sum of the 3 columns.
I use CASE WHEN but is seems that I could not use it in group by
SELECT #SELLING_AMOUNT=
CASE LOCK_SELLING_AMOUNT WHEN 1 THEN SELLING_AMOUNT
ELSE (ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
END
The error is like
The column'dbo.NRW_MONTH_DATA.LOCK_SELLING_AMOUNT' in the select list is invalid because the column is not included in the aggregate function or GROUP BY clause.
Thank you in advance.
I need the group by to calculate the sum of them. Each row has an object_id and a LOCK_SELLING_AMOUNT and other columns for one month, I want to use group to calculate the sum during month span.
It works well when I do not consider the LOCK_SELLING_AMOUNT
First, you don't want GROUP BY. So just use:
SELECT #SELLING_WATER = (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;
Now, the problem is that a column can change values on different rows. So, what row does LOCK_SELLING_AMOUNT come from? We could assume it is the same on all rows. Or perhaps you want an aggregation function:
SELECT #SELLING_WATER = (CASE WHEN MAX(LOCK_SELLING_AMOUNT) = 1
THEN MAX(CASE WHEN LOCK_SELLING_AMOUNT = 1 THEN SELLING_AMOUNT END)
ELSE (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
END)
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;

Dates by quarter

I would like to count number of birthdays by quarters in SQL Server
i.e. Between Jan 1 - March 31, April 1 - June 30, July 1 - Sep 30 & Oct 1 - Dec 31.
Please help me with the Date function in Sql Server to do this.
I pass BDate as DATETIME . I want to use this BDate to populate 4 fields of type int with counts for number of birthdays in each quarter.
Thanks.
As long as your "BDate" column is datetime, you can achieve this quite easily using this query:
SELECT DATEPART(QUARTER,BDATE), COUNT(*)
FROM TABLE1
GROUP BY DATEPART(QUARTER,BDATE)
ORDER BY DATEPART(QUARTER,BDATE) ASC
Here's a working fiddle using some random data: http://sqlfiddle.com/#!6/7734b/1
Data set up:
create table test (
d1 varchar(10),
d2 datetime
);
insert into test (d1,d2) values ('2015-01-28','2015-01-28');
insert into test (d1,d2) values ('2015-02-13','2015-02-13');
insert into test (d1,d2) values ('2015-07-19','2015-07-19');
insert into test (d1,d2) values ('2015-11-04','2015-11-04');
If you just want to get counts for each of the quarters present in your data:
select DATEPART(QUARTER, d2), count(*)
from test
group by DATEPART(QUARTER, d2);
You can use d1 or d2 (SQL Server will handle the varchar or datetime properly).
If you want to include all four quarters, even if they're not present in your data:
select qs.q, count(t.d2) as c
from (
SELECT 1 as q
UNION ALL
SELECT 2 as q
UNION ALL
SELECT 3 as q
UNION ALL
SELECT 4 as q) qs
left join test t
on qs.q = DATEPART(QUARTER, t.d2)
group by qs.q;
Again, you can use either d1 or d2, it doesn't matter. The "qs" query just gets the numbers 1 to 4, then that is outer joined to the table with the birth dates.
Please try this:
--replace '19000102' with your int column
select SUM(CASE WHEN DATEPART(MONTH,CONVERT (datetime,convert(char(8),19000102)))
IN (1,2,3)
THEN 1
ELSE 0
END) as 'Q1',
SUM(CASE WHEN DATEPART(MONTH,CONVERT (datetime,convert(char(8),19000102)))
IN (4,5,6)
THEN 1
ELSE 0
END) as 'Q2',
SUM(CASE WHEN DATEPART(MONTH,CONVERT (datetime,convert(char(8),19000102)))
IN (7,8,9)
THEN 1
ELSE 0
END) as 'Q3',
SUM(CASE WHEN DATEPART(MONTH,CONVERT (datetime,convert(char(8),19000102)))
IN (10,11,12)
THEN 1
ELSE 0
END) as 'Q4'