Calculating median of 3 columns in a BigQuery table - google-bigquery

I am trying to build a query to calculate median of 3 column values. My table looks like below,
Item
Column 1
Column 2
Column 3
A
10
12
4
B
5
14
20
C
15
5
4
I want to be able to output,
Item
Column 1
Column 2
Column 3
Median
A
10
12
4
10
B
5
14
20
14
C
15
5
4
5
I have tried percentile_cont() but that seems to be only for values in a single column. How do i achieve this?

Consider below approach
select *,
( select distinct percentile_disc(col, 0.5) over()
from unnest([Column1, Column2, Column3]) as col
) AS Median
from your_table
if applied to sample data in your question - output is

Have you tried this:
select Col1, Col2, Col3,
PERCENTILE_CONT([Col1, Col2, Col3], 0.5) OVER() AS Median
from tableName

Related

Counting SUM(VALUE) from previous cell

I have the following table:
A
Sum(Tickets)
01-2022
5
02-2022
2
03-2022
8
04-2022
1
05-2022
3
06-2022
3
07-2022
4
08-2022
1
09-2022
5
10-2022
5
11-2022
3
I would like to create the following extra column 'TotalSum(Tickets)' but I am stuck....
Anyone who can help out?
A
Sum(Tickets)
TotalSum(Tickets)
01-2022
5
5
02-2022
2
7
03-2022
8
15
04-2022
1
16
05-2022
3
19
06-2022
3
22
07-2022
4
26
08-2022
1
27
09-2022
5
32
10-2022
5
37
11-2022
3
40
You may use SUM() as a window function here:
SELECT A, SumTickets, SUM(SumTickets) OVER (ORDER BY A) AS TotalSumTickets
FROM yourTable
ORDER BY A;
But this assumes that you actually have a bona-fide column SumTickets which contains the sums. Assuming you really showed us the intermediate result of some aggregation query, you should use:
SELECT A, SUM(Tickets) AS SumTickets,
SUM(SUM(Tickets)) OVER (ORDER BY A) AS TotalSumTickets
FROM yourTable
GROUP BY A
ORDER BY A;
left join the same table where date is not bigger, then sum that for every date:
select
table1.date,
sum(t.tickets)
from
table1
left join table1 t
on t.date<= table1.date
group by
table1.date;

SQL analytics function window size based on result in window

I require a criteria for the window size based on the calculation in the window.
For example the calculation in column col_2:
idx
col_0
col_1
col_2
rows in window
1
A
10
30
1,2
2
A
20
NULL
-
3
A
50
50
3
4
B
10
50
4,5,6
5
B
10
NULL
-
6
B
30
30
6
Basically, col_2 means something like sum(col_1) in [30,50] for the window in col_0 based only on the following columns. A query could be like
SELECT *,
SUM(col_1) OVER (PARTITION BY col_0 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING WHERE SUM(col_1) BETWEEN 30 AND 50) AS col_2
FROM table
I didn't find any function or sql snippet which efficiently solves this problem.
Thanks for your help.

Row Number with specific window size

I want to group records by row numbers.
Like from row 1-3 in group 1 , 4-6 in group 2 , 7-9 in group 3 and so on.
Suppose below is the table structure:
Row NumberDataValue
1 A 10
2 A 5
3 A 1
4 A 33
5 A 2
6 A 127
1 B 1
2 B 0
3 B 7
4 B 7
5 B 5
6 B 8
7 B 1
8 B 0
I want a output like this:
GroupValue
1 10
1 5
1 1
2 33
2 2
2 127
1 1
1 0
1 7
2 7
2 5
2 8
3 1
3 0
I am using Oracle 11G.
I can achieve this using PL/SQL. But I have to use SQL only. As I have to use this query in a reporting tool.
If this is a duplicate question please provide the link of the answered question.
Subtract 1 from the column "RowNumber" and divide by 3.
Then use TRUNC() to get the integer part:
SELECT TRUNC(("RowNumber" - 1) / 3) + 1 "Group",
"Value"
FROM tablename
See the demo.
I would assume the name of the first column is ordering.
You can do:
select
1 + trunc(row_number() over(partition by data order by ordering) - 1) / 3,
value
from t
What you show looks like the output from something like this:
select ceil(rn/3) as grp, value
from your_table
order by rn;
Note that "row number" and "group" are reserved words/phrases which should not be used as column names. I used rn and grp instead.
I think the ceiling function is the simplest way to arrive at what you want. If you want to base it on the RowNumber column:
select ceil( RowNumber / 3.0) as grouping
If you want to calculate it yourself using row_number():
select ceil( row_number() over (order by RowNumber) / 3.0 ) as grouping

How to add two values of the same column in a table

Consider the following table?
ID COL VALUE
1 A 10
2 B 10
3 C 10
4 D 10
5 E 10
Output:
ID COL VALUE
1 A 10
2 B 20
3 C 30
4 D 40
5 E 50
Based on your (deleted) comment in output it is taking up the sum of the upper values, it sounds like you're wanting a cumulative SUM().
You can do this with a windowed function:
Select Id, Col, Sum(Value) Over (Order By Id) As Value
From YourTable
Output
Id Col Value
1 A 10
2 B 20
3 C 30
4 D 40
5 E 50
Please make use of the the below code to obtain the cumulative sum. The code is working as expected with SQL Server 2012.
DECLARE #Table TABLE (ID int, COL CHAR(2), VALUE int)
INSERT #Table
(ID,COL,[VALUE])
VALUES
(1,'A',10),
(2,'B',10),
(3,'C',10),
(4,'D',10),
(5,'E',10)
SELECT t.ID,t.COL,SUM(VALUE) OVER (ORDER BY t.ID) AS VALUE
FROM #Table t
Not really sure what you are asking for. If my assumption is correct, you want to SUM the contents of a column and group it.
Select sum(value), col
from table
group by col

Renumbering the records in Oracle and SQL Server

I have a table t with following values in col1 -
1
1
3
4
4
4
5
7
10
13
I need to renumber it as following, so it will erase the gaps between numbers.
1
1
2
3
3
3
4
5
6
7
I am able to find the gap ranges. Didn't find the way to renumber - tried to apply analytical function with row_num() but cannot get correct result. Code should work in both Oracle and SQL Server, so connect by level is probably not the best way.
That look like a DENSE_RANK, SQL-Server:
WITH CTE AS
(
SELECT Col1, RANK = DENSE_RANK() OVER (ORDER BY Col1 ASC)
FROM dbo.Table1
)
UPDATE CTE SET Col1 = RANK
WHERE Col1 <> RANK
I'm not familiar with Oracle (anymore) but there's also a Dense_Rank function.
Demo
COL1
1
1
2
3
3
3
4
5
6
7