Average of rows in SQL Server - sql

I have the below table
Col1 Col2 Col3 Col4 Col5
TotalAvg 68.79 65.39 88.21 63.14
I am already saving the total of all columns in the TotalAvg row but now I want to calculate the Average of the TotalAvg row. Can someone please tell me how I can calculate row average.
I am looking for
Select Avg(Col2,Col3,Col4,Col5)
where Col1 = 'TotalAvg'
Thanks

If some of them may have NULL values, you could still use AVG() inside an APPLY.
SELECT
yourTable.Col1,
RowStats.avg
FROM
yourTable
CROSS APPLY
(
SELECT
AVG(x) AS avg
FROM
(
SELECT yourTable.col2 AS x
UNION ALL
SELECT yourTable.col3 AS x
UNION ALL
SELECT yourTable.col4 AS x
UNION ALL
SELECT yourTable.col5 AS x
)
pivot
)
AS rowStats

If by chance you need a more dynamic approach (i.e. variable columns), and IF you're open to a TVF, consider the following:
EDIT
The 1st parameter is a delimited list of columns to exclude. For example: 'IDNr,Year,AnyOtherNumericCol'.
Example
Select A.*
,B.*
From YourTable A
Cross Apply [dbo].[tvf-Stat-Row-Agg]('',(Select A.* for XML Raw)) B
Returns
Col1 Col2 Col3 Col4 Col5 RetCnt RetSum RetMin RetMax RetAvg RetStd
TotalAvg 68.79 65.39 88.21 63.14 4 285.53 63.14 88.21 71.3825 11.4562162892757
The TVF if Interested
CREATE FUNCTION [dbo].[tvf-Stat-Row-Agg](#Exclude varchar(500),#XML xml)
Returns Table
As
Return (
Select RetCnt = Count(Value)
,RetSum = Sum(Value)
,RetMin = Min(Value)
,RetMax = Max(Value)
,RetAvg = Avg(Value)
,RetStd = Stdev(Value)
From (
Select Item = convert(varchar(100),xAttr.query('local-name(.)'))
,Value = try_convert(float,xAttr.value('.','varchar(max)'))
From #XML.nodes('//#*') x(xAttr)
) S
Where charindex(','+S.Item+',',','+#Exclude+',')=0
);
EDIT 2
If the columns are fixed, and performance is paramount, then...
Select A.*
,B.*
From YourTable A
Cross Apply (
Select AvgVal = avg(Value)
From (values (Col2)
,(Col3)
,(Col4)
,(Col5)
) B1(Value)
) B

Related

SQL how to count each value in multiple columns and same rows?

COL1
COL2
COL3
A
B
A
C
D
C
for example lets say I have a dataset like this. I want to count the values, each value in multiple columns and same rows. As a result it has to say the count of the values I put into.
2A 1B and
2C 1D
Anyone can help?
You don't count values in a row, you count values in a column. So, you use sql to reformat your data in to a single column, then count the values in the usual way.
SELECT
column_value,
COUNT(*)
FROM
(
SELECT col1 AS column_value FROM your_table
UNION ALL
SELECT col2 AS column_value FROM your_table
UNION ALL
SELECT col3 AS column_value FROM your_table
)
AS pivoted
GROUP BY
column_value
ORDER BY
column_value
As I commented, here is the code for the same. Can be optimized a bit by removing multiple select statements.
Declare #val Varchar(MAX);
Select #val=COALESCE(#val + ' ' + result, result)
FROM (
SELECT CONCAT(cnt,col) result FROM (
SELECT col, count(*)cnt FROM (
SELECT col
FROM
(
SELECT col1, col2, col3
from #temp
) AS cp
UNPIVOT
(
col FOR cols IN (col1, col2, col3 )
) AS up)t
group by col)t)t2
select #val

Create multiple columns from existing Hive table columns

How to create multiple columns from an existing hive table. The example data would be like below.
My requirement is to create 2 new columns from existing table only when the condition met.
col1 when code=1. col2 when code=2.
expected output:
Please help in how to achieve it in Hive queries?
If you aggregate values required into arrays, then you can explode and filter only those with matching positions.
Demo:
with
my_table as (--use your table instead of this CTE
select stack(8,
'a',1,
'b',2,
'c',3,
'b1',2,
'd',4,
'c1',3,
'a1',1,
'd1',4
) as (col, code)
)
select c1.val as col1, c2.val as col2 from
(
select collect_set(case when code=1 then col else null end) as col1,
collect_set(case when code=2 then col else null end) as col2
from my_table where code in (1,2)
)s lateral view outer posexplode(col1) c1 as pos, val
lateral view outer posexplode(col2) c2 as pos, val
where c1.pos=c2.pos
Result:
col1 col2
a b
a1 b1
This approach will not work if arrays are of different size.
Another approach - calculate row_number and full join on row_number, this will work if col1 and col2 have different number of values (some values will be null):
with
my_table as (--use your table instead of this CTE
select stack(8,
'a',1,
'b',2,
'c',3,
'b1',2,
'd',4,
'c1',3,
'a1',1,
'd1',4
) as (col, code)
),
ordered as
(
select code, col, row_number() over(partition by code order by col) rn
from my_table where code in (1,2)
)
select c1.col as col1, c2.col as col2
from (select * from ordered where code=1) c1
full join
(select * from ordered where code=2) c2 on c1.rn = c2.rn
Result:
col1 col2
a b
a1 b1

SQL Server - minimum value on row

I have a table with a single row and two columns. Can I obtain the minimum value from the row using an SQL query?
value1 value2
1 43 39
The query should return the value 39.
The simplest method is probably apply:
select t.*, v.min_val
from t cross apply
(select min(val) as min_val
from (values (value1), (value2)) v(val)
) v;
For just two values that are not-null, you a case expression is also simple:
select t.*,
(case when value1 < value2 then value1 else value2 end) as min_val
from t;
However, this does not ignore null values. And it does not generalize quite as easily as one would like.
Certainly Gordon's answer (+1) is more performant and would be my first choice, but if by chance you are looking for a more "generalized" version, here is a simplified JSON approach.
This may be helpful if you have numerous or variable columns.
Example
Declare #YourTable table (ID int,value1 int,value2 int)
Insert into #YourTable values
(1,43,39)
Select A.*
,B.*
From #YourTable A
Cross Apply (
Select RowMin = min(Value)
From ( Select Value=try_convert(int,Value) -- << Set desired Datatype
From OpenJson( (Select A.* For JSON Path,Without_Array_Wrapper ) )
Where [Key] not in ('ID')
) J
) B
Returns
ID value1 value2 RowMin
1 43 39 39

SQL script for retrieving 5 unique values in a table ( google big query )

I am looking for a query where I can get unique values(5) in a table. For example.
The table consists of more 100+ columns. Is there any way I can get unique values.
I am using google big query and tried this option
select col1 col2 ... coln
from tablename
where col1 is not null and col2 is not null
group by col1,col2... coln
order by col1, col2... coln
limit 5
But problem is it gives zero records if all the column are null
Thanks
R
I think you might be able to do this in Google bigquery, assuming that the types for the columns are compatible:
select colname, colval
from (select 'col1' as colname, col1 as colvalue
from t
where col1 is not null
group by col1
limit 5
),
(select 'col2' as colname, col2 as colvalue
from t
where col2 is not null
group by col2
limit 5
),
. . .
For those not familiar with the syntax, a comas in the from clause means union all, not cross join in this dialect. Why did they have to change this?
Try This one, i hope it works
;With CTE as (
select * ,ROW_NUMBER () over (partition by isnull(col1,''),isnull(col2,'')... isnull(coln,'') order by isnull(col1,'')) row_id
from tablename
) select * from CTE where row_id =1

sort items based on their appears count

I have data like this
d b c
a d
c b
a b
c a
c a d
c
if you analyse, you will find the appearance of each element as follows
a: 4
b: 3
c: 5
d: 2
According to appearance my sorted elements would be
c,a,b,d
and final output should be
c b d
a d
c b
a b
c a
c a d
c
Any clue, how we can achieve this using sql query ?
Unless there is another column which dictates the order of the input rows, it will not be possible to guarantee that the output rows are returned in the same order. I've made an assumption here to order them by the three column values so that the result is deterministic.
It's likely to be possible to compact this code into fewer steps, but shows the steps reasonably clearly.
Note that for a large dataset, it may be more efficient to partition some of these steps into SELECT INTO operations creating temporary tables or work tables.
DECLARE #t TABLE
(col1 CHAR(1)
,col2 CHAR(1)
,col3 CHAR(1)
)
INSERT #t
SELECT 'd','b','c'
UNION SELECT 'a','d',NULL
UNION SELECT 'c','b',NULL
UNION SELECT 'a','b',NULL
UNION SELECT 'c','a',NULL
UNION SELECT 'c','a','d'
UNION SELECT 'c',NULL,NULL
;WITH freqCTE
AS
(
SELECT col1 FROM #t WHERE col1 IS NOT NULL
UNION ALL
SELECT col2 FROM #t WHERE col2 IS NOT NULL
UNION ALL
SELECT col3 FROM #t WHERE col3 IS NOT NULL
)
,grpCTE
AS
(
SELECT col1 AS val
,COUNT(1) AS cnt
FROM freqCTE
GROUP BY col1
)
,rowNCTE
AS
(
SELECT *
,ROW_NUMBER() OVER (ORDER BY col1
,col2
,col3
) AS rowN
FROM #t
)
,buildCTE
AS
(
SELECT rowN
,val
,cnt
,ROW_NUMBER() OVER (PARTITION BY rowN
ORDER BY ISNULL(cnt,-1) DESC
,ISNULL(val,'z')
) AS colOrd
FROM (
SELECT *
FROM rowNCTE AS t
JOIN grpCTE AS g1
ON g1.val = t.col1
UNION ALL
SELECT *
FROM rowNCTE AS t
LEFT JOIN grpCTE AS g2
ON g2.val = t.col2
UNION ALL
SELECT *
FROM rowNCTE AS t
LEFT JOIN grpCTE AS g3
ON g3.val = t.col3
) AS x
)
SELECT b1.val AS col1
,b2.val AS col2
,b3.val AS col3
FROM buildCTE AS b1
JOIN buildCTE AS b2
ON b2.rowN = b1.rowN
AND b2.colOrd = 2
JOIN buildCTE AS b3
ON b3.rowN = b1.rowN
AND b3.colOrd = 3
WHERE b1.colOrd = 1
ORDER BY b1.rowN