generate a table that keep showing individual rows - sql

I have just started learning sql and I have a question:
Which function we should use to generate a table that keep showing individual rows but able to calculate per group?
Is it CTE, Group By, Aggregate, or Window?
Thanks

CTE is not a function
GROUP BY will group rows with additional calculations per group
WINDOW functions compute values over a group of rows and return a single result for each row.
So the answer is WINDOW functions since GROUP BY will not retain individual records.
An example:
GROUP BY
SELECT
letter,
SUM(number) AS aggregate
FROM
(
SELECT
'A' AS letter,
2 AS number
UNION ALL
( SELECT
'A' AS letter,
3 AS number)
UNION ALL
( SELECT
'C' AS letter,
6 AS number)
) AS table_3
GROUP BY
letter
Output:
letter
aggregate
A
5
C
6
WINDOW
SELECT
letter,
SUM(number) OVER (PARTITION BY letter) AS `window`
FROM
(
SELECT
'A' AS letter,
2 AS number
UNION ALL
( SELECT
'A' AS letter,
3 AS number)
UNION ALL
( SELECT
'C' AS letter,
6 AS number)
) AS table_3
Output:
letter
window
A
5
A
5
C
6
Source: https://count.co/sql-resources/bigquery-standard-sql/window-functions-explained

Related

Trying to create Row number for Distinct values in BigQuery

On BigQuery, I'm trying to get the row count of the distinct values to display for easy reference.
Assuming I have 1000 distinct values and I'm trying to get the 340th row of distinct value, how should i code it.
I tried to run
SELECT
DISTINCT column_2
FROM
table
and sure it turns out all the DISTINCT values of column_2. But how do i add the row number beside, and would I be able to put a WHERE for the row number?
Consider below approach
select distinct column_2
from your_table
qualify 340 = dense_rank() over(order by column_2)
Since BigQuery works parallelized there is no guarantee/need for any sorting of table rows. That also means there are no row numbers.
If you want the nth element of a query result you need to define a sorting logic beforehand. You can use navigational functions for that, or a LIMIT with OFFSET if you need one exact value
with t as (
select 'a' as val
union all select 'a'
union all select 'b'
union all select 'c'
union all select 'c'
union all select 'f'
union all select 'y'
union all select 'z'
union all select 'a'
)
select
distinct val
from t
order by 1
-- 5th element has offset 4
limit 1 offset 4

How to SUM via Group By?

I have a table something like this:
ID Marks Weightatthistime
1 5 44
1 5 43
1 5 41
2 4 39
2 4 38
I want the total marks obtained by the IDs, so I want my query to return: 9.
I know I could do a:
select ID, sum(Marks) from table group by 1
but I simply just want the total sum and not another mini table. The table is aggregated at this level and there's no way for me to change it.
Use subquery :
select id, sum(marks)
from (select distinct id, marks
from table t
) t
group by id;
If you want only sum then use only sum(marks) :
select sum(marks)
from (select distinct id, marks
from table t
) t;
use distinct
select sum( distinct Marks) from table
with cte as
(
select 1 id, 5 as m union all
select 1,5 union all
select 1,5 union all
select 2,4 union all
select 2,4
) select sum(distinct m) from cte
but if multiple user have same number then follow subquery method that #Yogesh shown
output
9
I believe this should work with any ANSI SQL engine.
Select ID, Marks, Weightatthistime, (Select Sum(Marks) From Table1) SumAllMarks
From Table1
This will put 9 on each record.
SELECT sum(DISTINCT marks) FROM table;
You can use this query to get the sum of the distinct mark values.

Counting from 2 columns in SQL server

In essence I have one table with two columns
One Two
-----------
A B
B C
C D
and I want to count the number of A's through D.
Resulting
Letter Count
---------------
A 1
B 2
C 2
D 1
My code now is
Select one, count("") from table
group by one
union
Select two, count("*") from table
group by two
Right now I am getting
Letter Count
---------------
A 1
B 1
B 1
C 1
C 1
D 1
How do I fix it?
Try this
SELECT Count(a),
a
FROM (SELECT cola a
FROM table
UNION ALL
SELECT colb a
FROM table) c
GROUP BY a
select letter, sum(total) from
(
Select one as letter, count(1) as total from tablename
group by one
union all
Select two as letter, count(1) as total from tablename
group by two) as t1
group by t1.letter
order by t1.letter asc
there is no reason to group twice.
select letter, count(*) as total_cnt
from
(
Select one as letter from table
union all
Select two as letter from table
)
group by letter;
You can do this
SELECT LETTER,
count(*) AS _count
FROM (
SELECT One AS Letter
FROM Test
UNION ALL
SELECT Two AS Letter
FROM Test
) T1
GROUP BY LETTER

understand the resultset of the below query

with sample_data as (
select 1 id, 1 num, 'Hello' val from dual union all
select 1 id, 2 num, 'Goodbye' val from dual union all
select 2 id, 2 num, 'Hey' val from dual union all
select 2 id, 4 num, 'What''s up?' val from dual union all
select 3 id, 5 num, 'See you' val from dual)
select id,
NUM,
CASE
WHEN ID=1 THEN
SUM(NUM) OVER (PARTITION BY CASE WHEN NUM=3 THEN ID END )
END AS SUM_1,
from sample_data
Can any one help me to understand the how this query will work..case inside the partition make me difficult to understand the resultset for this query. I am l
(Ignoring the comma before the from that generates a syntax error.)
There are two case statements. The outer one is saying "I'm only going to assign a number when the id is 1. Everything else will get a NULL value.
The inner one is calculating the value. It is splitting the data into two groups, those with num = 3 and everything else. The calculation is the sum of num.
So, the query is doing the following. It is assigning the sum of num where either num is equal to 3 or not equal to 3 to each row where id = 1.

Union returns two rows if data is different, one if it's the same! Why?

Taking the following statement:
select count( 1 ) as cnt from tbl where val= 1
union
select count( 1 ) as cnt from tbl where val = 0
If the two selects return the same value the result is a single row with that value. If the selects return different values the result is two rows with the two values. Why?
I am trying to find the total count of rows using:
select sum (cnt) from
(
select count( 1 ) as cnt from tbl where value = 1
union
select count( 1 ) as cnt from tbl where value = 0
) as tbl2
which works as expected if the counts are different but gives half the value if the counts are the same...
(PS : More interested in why sql behaves this way than in a solution)
This behavior is by design. You should use UNION ALL to achieve the behavior you want. Basically, UNION performs a set union operation, removing the duplicates in the set.
http://www.fmsinc.com/free/NewTips/SQL/SQLtip5.asp
the main difference between union and union all is that union does a distinct over all fields returned. Where union all just returns and joins the various result sets