SQL multiply by AVG - sql

I have a column ([A]) with some numbers - say A1, A2, A3.... And and I need to have a second one ([B]) which is a result of multiplying first one with average of all numbers there - e.g.
B1=A1*(A1+A2+.....+An)/n
B2=A2*(A1+A2+.....+An)/n
and so on. MS SQL Server 2016

This should do it:
SELECT a * AVG(a) OVER () AS b
FROM t
AVG(a) is identical to SUM(a) / COUNT(a)
AVG(a) OVER () is identical to SELECT AVG(a) FROM t.

Try this:
select A as A, A * (select sum(A) from tbl) / (select count(A) from tbl) as B
from tbl

you can use window function
select A ,A*( sum(A) over()/count(A)over()) as B
from table

Have a derived table (the sub-query), where you calculate sum(A) and n. CROSS JOIN.
select t1.A * t2.sumA / t2.n
from tablename t1
cross join (select sum(A) as sumA, count(*) as n from tablename) t2

Related

SQL Server query for all columns with group by and having

I'm wondering is there a way to query all columns with group by and having in SQL Server? For example, I have 6 columns, a, b,…,f, and this is something I want to get:
Select *
From table
Group by table.b, table.c
Having max(table.d)=table.d
This works in sybase, since I'm trying to migrate stuff from sybase to SQL Server, I'm not sure what I can do in new environment. Thanks.
Why do you want to group by every column when you don't use any aggragate-functions in your select? Just use the following code to get all columns of the table:
select * from table
Group by only gets used when you have aggragete-functions (e.g. max(), avg(), count(), ...) in your select.
Having limits the aggrageted columns and where the normal columns of the table.
You can use MIN, MAX, AVG, and COUNT functions with the OVER clause to provide aggregated values for each column (to imitate the group by clause for each column) and Common table expression CTE to filter out the results (to imitate the having clause) as:
;With CTE as
(
SELECT
MIN(a) OVER (PARTITION BY a) AS MinCol_a
, MAX(b) OVER (PARTITION BY b) AS MaxCol_b
, AVG(c) OVER (PARTITION BY c) AS AvgCol_c
, COUNT(e) OVER (PARTITION BY d) AS Counte_PerCol_d
FROM Tbl_Test
)
select MinCol_a,MaxCol_b ,AvgCol_c,Counte_PerCol_d
from CTE
Join --here you can join the table Test results with other tables
where --any filter condition similar to Having clause
If what you want is to get the rows with maximum d for each combination of b and c then use NOT EXISTS:
select t.* from tablename t
where not exists (
select 1 from tablename
where b = t.b and c = t.c and d > t.d
)
or with rank() window function:
select t.a, t.b, t.c, t.d, t.e, t.f
from (
select *,
rank() over (partition by b, c order by d desc) rn
from tablename
) t
where t.rn = 1
Without using having you can get the result which you want. Try below
Select table.b, table.c, max(table.d)
From table
Group by table.b, table.c

How can i divide two expressions in Microsoft SQL Server

How can i divide two expressions in Microsoft SQL Server which give Numbers as a Result? I tried with a /, but this didn't work
SELECT COUNT(*) FROM A
SELECT COUNT(*) FROM B WHERE c = 1
I tried with / but this didnt work
SELECT COUNT(*)
FROM A/SELECT COUNT(*) FROM B WHERE c = 1
It might depend on RDBMS, this works in sql server.
SELECT ACounts/ CAST(BCounts AS Decimal(29,20))
FROM (SELECT COUNT(*) AS ACounts FROM A) AS suba
, (SELECT COUNT(*) AS BCounts FROM B WHERE c = 1) AS subb
Note that I cast the BCounts to a decimal of arbitrary size otherwise it will round off to the nearest whole number. Ignore that part if that is what you wanted.
This also works
SELECT (SELECT COUNT(*) AS ACounts FROM A)/ CAST((SELECT COUNT(*) AS BCounts FROM B WHERE c = 1) AS Decimal(29,20))
Use subqueries:
SELECT (a.countA / b.countB) As divisionResult
FROM
(SELECT COUNT(*) AS countA FROM A) a,
(SELECT COUNT(*) AS countB FROM B WHERE c = 1) b
;

GROUP BY one column to find MAX, but keep value from another column - SQL

A | B | num
----------------------
123 1 2
123 10 5
Result:
A | B | max_num
-------------------------
123 10 5
Let's say the table name is tab, currently I have
SELECT T.A, MAX(T.num) AS max_num
FROM tab T
GROUP BY T.A
However, the result will not contain the column B.
SELECT T.A, T.B... GROUP BY T.A, T.B
Will also not give the desired result, since max is found based on the A,B pair.
How can I choose the max of num grouped by only A, but then keep the value of B for the max row that is chosen?
1.Select Max num from table
2.Just filter of IN Clause
select * from Mytable where
num in(
select TOP 1 MAX(num)
from mytab
group by colA)
or
For SQL SERVER
You can Use Window function for single Max using ROW_NUMBER ()
select * from (
select ROW_NUMBER () OVER (ORDER BY num desc) rn,*
from tab
)d where d.rn=1
This should do the job:
Select t1.A, T1.B,T1.num from tab t1 where (T1.A,T1.num) in (
SELECT T.A, MAX(T.num) AS max_num
FROM tab T
GROUP BY T.A)
Selection the Record where num equals the max(num)
See the SQLFIDDLE
Do you mean you want the whole rows where c = the max(c) value for each a? This one will give both rows if it's a tie:
select a, b, c
from t as t1
where c = (select max(c) from t t2
where t1.a = t2.a)

How to get Original Rows filtered by a HAVING Condition?

What is the method in T-SQL to select the orginal values limited by a HAVING attribute. For example, if I have
A|B
10|1
11|2
10|3
How would I get all the values of B (Not An Average or some other summary stat), Grouped by A, having a Count (Occurrences of A) greater than or equal two 2?
Actually, you have several options to choose from
1. You could make a subquery out of your original having statement and join it back to your table
SELECT *
FROM YourTable yt
INNER JOIN (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
) cnt ON cnt.A = yt.A
2. another equivalent solution would be to use a WITH clause
;WITH cnt AS (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
)
SELECT *
FROM YourTable yt
INNER JOIN cnt ON cnt.A = yt.A
3. or you could use an IN statement
SELECT *
FROM YourTable yt
WHERE A IN (SELECT A FROM YourTable GROUP BY A HAVING COUNT(*) >= 2)
A self join will work:
select B
from table
join(
select A
from table
group by 1
having count(1)>1
)s
using(A);
You can use window function (no joins, only one table scan):
select * from (
select *, cnt=count(*) over(partiton by A) from table
) as a
where cnt >= 2

SELECT SUM as field

Suppose i have this table
table (a,b,c,d). Datatypes are not important.
I want to do this
select a as a1,b as b1,c as c1,
(select sum(d) from table where a=a1 and b=b1) as total
from table
group by a,b,c
...but I can't find a way (sqldeveloper keeps complaining with "from clause not found".)
Is there a way? Is it possible?
SELECT a as a1,b as b1,c as c1,
(
SELECT SUM(d)
FROM mytable mi
WHERE mi.a = mo.a
AND mi.b= mo.b
) as total
FROM mytable mo
GROUP BY
a, b, c
It's much more simple and efficient to rewrite it as this:
SELECT a AS a1, B AS b1, c AS c1, SUM(SUM(d)) OVER (PARTITION BY a, b) AS total
FROM mytable
GROUP BY
a, b, c
Note the SUM(SUM(d)) here.
The innermost SUM is the aggregate function. It calculates the SUM(d) a-b-c-wise.
The outermost SUM is the analytic function. It sums the precalculated SUM(d)'s a-b-wise, and returns the value along with each row.
Du you mean something like this?
select a as a1,
b as b1,
c as c1,
sum(sum(d)) OVER (PARTITION BY a, b) AS total
from table
group by a,b,c
you can do it with aliases:
SELECT a AS a1, b AS b1, c AS c1,
(SELECT SUM(d)
FROM test_t t_in
WHERE t_in.a = t.a
AND t_in.b = t.b) AS total
FROM test_t t
GROUP BY a, b, c