How to I Pivot this table? - sql

I have created a table that looks something like this:
I want to Pivot this table such that it looks like;
I have tried some other posts about PIVOTs but I could not understand how to do it with more than 2 columns, nor when the values inside the table are sums from different variables.

You want to transpose the recordset (unpivot, then pivot on a different exis). A portable solution is to use union, and then conditional aggregation:
select
name,
max(case when category = 'A' then val end) as valA,
max(case when category = 'B' then val end) as valB
from (
select category, premium val, 'premium' name from mytable
union all select category, net_premium, 'net_premium' from mytable
union all select category, claims, 'claims' from mytable
union all select category, fees, 'fees' from mytable
union all select category, expenses, 'expenses' from mytable
union all select category, commissions, 'commissions' from mytable
) x
group by name
Important: for union to work, the datatypes of all columns being unioned must be the same (it seems like it is the case with your data, that as decimal values everywhere). If not, you need to do conversions in order to align the datatypes.

Related

Counting the count of distinct values from two columns in sql

I have a table in data base in which there are corresponding values for the primary key.
I want to count the distinct values from two columns.
I already know one method of using union all and then applying groupby on that resultant table.
Select Id,Brand1
into #Temp
from data
union all
Select Id,Brand2
from data
Select ID,Count(Distinct Brand1)
from #Temp
group by ID
Same thing we can do in big query also using temp table only.
Sample Table
ID Brand1 Brand2
1 A B
1 B C
2 D A
2 A D
Resultant Table
ID Distinct_Count_Brand
1 3
2 2
As you can see in this column Distinct_count_Brand It is counting the unique count of Brand from two columns Brand1 and Brand2.
I already know one way (Basically unpivoting) but want to know if there is some other way around to count unique values from two columns.
I don't know BigQuery's quirks, but perhaps you can just inline the union query:
SELECT ID, COUNT(DISTINCT Brand)
FROM
(
SELECT ID, Brand1 AS Brand FROM data
UNION ALL
SELECT ID, Brand2 FROM data
) t
GROUP BY ID;
In SQL Server, I woud use:
Select b.id, count(distinct b.brand)
from data d cross apply
(values (id, brand1), (id, brand2)) b(id, brand)
group by b.id;
Here is a db<>fiddle.
In BigQuery, the equivalent would be expressed as:
select t.id, count(distinct brand)
from t cross join
unnest(array[brand1, brand2]) brand
group by t.id;
Here is a BQ query that demonstrates that this works:
with t as (
select 1 as id, 'A' as brand1, 'B' as brand2 union all
select 1, 'B', 'C' union all
select 2, 'D', 'A' union all
select 2, 'A', 'D'
)
select t.id, count(distinct brand)
from t cross join
unnest(array[brand1, brand2]) brand
group by t.id;

Select a third column based on two distant rows within the same table

I want to select a third column based on two distant columns within the same table.
I could only think of this:
select tl.thirdcolumn
from table1 t1
WHERE
EXISTS
(
Select distinct tl.firstcolumn , t1.secondcolumn
From t1
)
This:
select distinct tl.thirdcolumn
from table t1
won't work as I don't want the distinct thirdrow. I want the thirdrow to be based on the first two rows being distinct.
I guess its a kind of nested sql statment with a select top 1... idk
CATEGORY NAME Query
---------------------------------------------------
STUDENTS NUMBER_OF_CHAPTERS QueryA
STUDENTS NUMBER_OF_STUDENT_MEMBERS QueryB
STUDENTS NUMBER_OF_STUDENT_MEMBERS QueryB
MEMBERS NUMBER_OF_MEMBERS_WORLDWIDE QueryC
MEMBERS NUMBER_OF_MEMBERS_WORLDWIDE QueryC
Your question is rather hard to follow, but I think you might simply want group by:
select tl.firstcolumn , t1.secondcolumn, max(tl.thirdcolumn)
from table1 t1
group by tl.firstcolumn , t1.secondcolumn;
If you want rows where the pair of values only appears once, then add having count(*) = 1:
select tl.firstcolumn , t1.secondcolumn, max(tl.thirdcolumn)
from table1 t1
group by tl.firstcolumn , t1.secondcolumn
having count(*) = 1;
Query -
SELECT
CATEGORY,NAME,QUERY
FROM
(
WITH TAB AS (
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_CHAPTERS' AS NAME,
'QUERYA' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_STUDENT_MEMBERS' AS NAME,
'QUERYB' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_STUDENT_MEMBERS' AS NAME,
'QUERYB' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'MEMBERS' AS CATEGORY,
'NUMBER_OF_MEMBERS_WORLDWIDE' AS NAME,
'QUERYC' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'MEMBERS' AS CATEGORY,
'NUMBER_OF_MEMBERS_WORLDWIDE' AS NAME,
'QUERYC' AS QUERY
FROM
DUAL
) SELECT
CATEGORY,
NAME,
QUERY,
COUNT(*) OVER(PARTITION BY
CATEGORY,
NAME
ORDER BY
CATEGORY,
NAME,
QUERY
) AS RNK
FROM
TAB
)
WHERE
RNK = 1;
Output -
"CATEGORY","NAME","QUERY"
"STUDENTS","NUMBER_OF_CHAPTERS","QueryA"

disply two rows from single row

This is the given table:
I need to get this data without creating temporary table based on the above table:
We can't use temporary table. I need to display the data with sql query only.
Try this
SELECT company name,'No' as value, clicks as data
from table1
union all
SELECT company,'Yes', (clicks - impression)
from table1
order by name,val
You can use UNION ALL to unpivot your table:
SELECT
company,
'No' AS val,
impression AS data
FROM tbl
UNION ALL
SELECT
company,
'Yes' AS val,
clicks - impression AS data
FROM tbl
ORDER BY company, val
You need UNION ALL
SELECT company,'No' val, impression as data from your_table
union all
SELECT company,'Yes' val, clicks-impression as data from your_table
select company as name, 'No' as val, impression as data
from tbl
union
select company as name, 'Yes' as val, clicks - impression as data
from tbl
SELECT COMPANY AS NAME, 'YES' AS VAL, (CLICKS-IMPRESSIONS) AS DATA
FROM ORIGINAL_TABLE
UNION
SELECT COMPANY AS NAME, 'NO' AS VAL, IMPRESSIONS AS DATA
FROM ORIGINAL_TABLE
If you want them sorted: Try this:
SELECT A.NAME, A.VAL, A.DATA FROM
(SELECT COMPANY AS NAME, 'YES' AS VAL, (CLICKS-IMPRESSIONS) AS DATA
FROM OR_TABLE
UNION
SELECT COMPANY AS NAME, 'NO' AS VAL, IMPRESSIONS AS DATA
FROM OR_TABLE) A
ORDER BY A.NAME ASC;

Union all on the same table

There has to be a better way of doing this any one have an idea. there is one table and i have 8 columns i need select all of the columns one on top of each other and for each selected colum i need to count the number of items that are the same
SELECT Col1, count(*) 'Selected'
FROM [Table]
group by temp_id,Col1
UNION ALL
SELECT Col2,count(*)
FROM [Table]
group by temp_id,Col2
having len(ltrim(rtrim(Col2)))<>0
UNION ALL
SELECT Col3,count(*)
FROM [Table]
group by temp_id,Col3
having len(ltrim(rtrim(Col3)))<>0
union all
SELECT Col4,count(*)
FROM [Table]
group by temp_id,Col4
union all
SELECT Col5,count(*)
FROM [Table]
group by temp_id,Col5
having len(ltrim(rtrim(Col5)))<>0
union all
SELECT Col6,count(*)
FROM [Table]
group by temp_id,Col6
having len(ltrim(rtrim(Col6)))<>0
union all
SELECT Col7,count(*)
FROM [Table]
group by temp_id,Col7
having len(ltrim(rtrim(Col7)))<>0
union all
SELECT Col8,count(*)
FROM [Table]
group by temp_id,Col8
having len(ltrim(rtrim(Col8)))<>0
There is. It is called grouping sets (and it is documented here). In your case, you can do something like this (example for first three columns):
select coalesce(col1, col2, col3), count(*) as Selected
from [table]
group by grouping sets ((temp_id, col1), (temp_id, col2), (temp_id, col3));
Your condition using length() and trim() on each column -- you should probably handle that using a having clause.

Counting the rows of a column where the value of a different column is 1

I am using a select count distinct to count the number of records in a column. However, I only want to count the records where the value of a different column is 1.
So my table looks a bit like this:
Name------Type
abc---------1
def----------2
ghi----------2
jkl-----------1
mno--------1
and I want the query only to count abc, jkl and mno and thus return '3'.
I wasn't able to do this with the CASE function, because this only seems to work with conditions in the same column.
EDIT: Sorry, I should have added, I want to make a query that counts both types.
So the result should look more like:
1---3
2---2
SELECT COUNT(*)
FROM dbo.[table name]
WHERE [type] = 1;
If you want to return the counts by type:
SELECT [type], COUNT(*)
FROM dbo.[table name]
GROUP BY [type]
ORDER BY [type];
You should avoid using keywords like type as column names - you can avoid a lot of square brackets if you use a more specific, non-reserved word.
I think you'll want (assuming that you wouldn't want to count ('abc',1) twice if it is in your table twice):
select count(distinct name)
from mytable
where type = 1
EDIT: for getting all types
select type, count(distinct name)
from mytable
group by type
order by type
select count(1) from tbl where type = 1
;WITH MyTable (Name, [Type]) AS
(
SELECT 'abc', 1
UNION
SELECT 'def', 2
UNION
SELECT 'ghi', 2
UNION
SELECT 'jkl', 1
UNION
SELECT 'mno', 1
)
SELECT COUNT( DISTINCT Name)
FROM MyTable
WHERE [Type] = 1