how to write this query in sql-server? - sql

This is my table structure in sql-server:
id Marks
---------- -----------
AAA 50
KKK 87
KKK 89
BBB 48
CCC 54
AAA 52
DDD 55
BBB 60
XXX 99
This is the desired output:
Name attempts Max Mark
------- ---------------- ------------
AAA 2 52
kkk 2 89
BBB 2 60
CCC 1 54
DDD 1 55
XXX 1 99
I've tried this but it seems incorrect:
SELECT
name,
count(*) as attempts,
max(marks)
FROM table_name
GROUP BY name, attempts, max_marks

Try this one:
SELECT
id AS Name,
count(id) AS attempts,
max(Marks) AS Max_Mark
FROM table_name
GROUP BY id

You were on the right track just added too much to grouping field,
SELECT id AS name
,COUNT(*) AS Attempts
,MAX(marks) as MaxMarks
FROM table_name
GROUP BY id
If your column is already part of aggregate function such as MAX or COUNT it does not need to be included in GROUP BY clause

Related

How to find the top n quantities within a table

Suppose in the table mentioned below, I wanted to select the top 3 quantities and if there are duplicates, I want them too and the required table is mentioned below too.
For this requirement, I tried something like the SQL below.
select name, quantity
from employee
order by name,quantity DESC
FETCH FIRST 3 ROWS WITH TIES;
But I'm not able to get any meaningful output. BTW I'm using postgres.
All I need is employee info along with quantities with 3 max quantities along with ties if any.
NAME | Quantity
---------
AAA 500
AAA 500
AAA 400
AAA 300
AAA 200
AAA 100
Required Table:
NAME | Quantity
--------------
AAA 500
AAA 500
AAA 400
AAA 300
```
This can be achieved by using dense_rank.
select "NAME"
,"Quantity"
from (
select *
,dense_rank() over(order by "Quantity" desc) as dr
from t
) t
where dr <= 3
NAME
Quantity
AAA
500
AAA
500
AAA
400
AAA
300
Fiddle

finding manager id from employee table

I have a table data like in the below.
Emp_id Emp_name Dept_id
111 aaa 1
222 bbb 2
333 ccc 3
444 ddd 4
555 eee 5
Then i want to populate new column manager id as next emp_id from the employee table like in the below.
Emp_id Emp_name Dept_id Manager_id
111 aaa 1 222
222 bbb 2 333
333 ccc 3 444
444 ddd 4 555
555 eee 5 111
Thanks for your help in advance!
You can return the value as:
select t.*,
coalesce(lead(empid) over (order by empid),
min(empid) over ()
) as manager_id
from t;
Perhaps a select query is sufficient. Actually modifying the table is a bit tricky and the best syntax depends on the database.

calculate Count and Sum from two different table with group by without using inner query

I have two table first A having column id,phone_number,refer_amount
and second B having column phone_number,transaction_amount
now i want sum() of refer_amount and transaction_amount and count() of phone_number from both table using group by phone_number without using inner query
Table A
phone_number refer_amount
123 50
456 80
789 90
123 90
123 80
123 20
456 20
456 79
456 49
123 49
Table B
phone_number transaction_amount
123 50
123 51
123 79
456 22
456 11
456 78
456 66
456 88
456 88
456 66
789 66
789 23
789 78
789 46
i have tried following query but it gives me wrong output:
SELECT a.phone_number,COUNT(a.phone_number) AS refer_count,SUM(a.refer_amount) AS refer_amount,b.phone_number,COUNT(b.phone_number) AS toal_count,SUM(b.transaction_amount) AS transaction_amount FROM dbo.A AS a,dbo.B AS b WHERE a.phone_number=b.phone_number GROUP BY a.phone_number,b.phone_number
output (wrong):
phone_number refer_count refer_amount phone_number transaction_count transaction_amount
123 15 867 123 15 900
456 28 1596 456 28 1676
789 5 450 789 5 291
output (That I want):
phone_number refer_count refer_amount phone_number transaction_count transaction_amount
123 5 289 123 3 180
456 4 228 456 7 419
789 1 90 789 5 291
I would do the aggregations on the B table in a separate subquery, and then join to it:
SELECT
a.phone_number,
COUNT(a.phone_number) AS a_cnt,
SUM(a.refer_amount) AS a_sum,
COALESCE(b.b_cnt, 0) AS b_cnt,
COALESCE(b.b_sum, 0) AS b_sum
FROM A a
LEFT JOIN
(
SELECT
phone_number,
COUNT(*) AS b_cnt,
SUM(transaction_amount) AS b_sum
FROM B
GROUP BY phone_number
) b
ON a.phone_number = b.phone_number;
One major potential issue with your current approach is that the join could result in duplicate counting, as a given phone_number record in the A table gets replicated due to the join.
Speaking of joins, note that above I use an explicit join, rather than the implicit one you were using. In general, you should not put commas into the FROM clause.
This can help. You don't need sum(b.phone_number) when checking for a.phone_number = b.phone_number. Distinct is needed for phone number as there are two columns to consider.
For group by, anything not in aggregate function needs to be in group by function.
select a.phone_number, count(distinct a.phone_number), sum(a.refer_amount),
sum (b.transaction_amount)
from A as a, B as b
where a.phone_number=b.phone_number
group by a.phone_number

SQL Joins based on two tables

I would like to combine two tables and obtain total# of the name by count() and group by functions.
Table_1 is shown below as;
name branch sports player no
---- ----- ------ --------
Mike 120 basketball 15
David 110 soccer 18
Table_2 is shown below as;
jersey color player no height
---------- --------- ------
Blue 15 182
Green 18 174
I tried to combine two tables by inner joins and count them based on the name such as;
SELECT name, branch, sports,
FROM TABLE_1
INNER JOIN TABLE_2
ON
TABLE_1.player no = TABLE_2.player no
COUNT(name) AS TOTAL
GROUP BY name, branch, sports, jersey color, player no, height
output should be
name branch player no jersey color height
---- ------ ------- -------- ----
Mike 120 15 Blue 182
David 110 18 Green 174
Mike 120 15 Blue 182
Mike 120 15 Blue 182
David 110 18 Green 174
After count(name)
name branch player no jersey color height Total
---- ------ ------- -------- ---- -----
Mike 120 15 Blue 182 3
David 110 18 Green 174 2
I have been pondering why I can not make this works?
You are essentially trying to combine the results one after the other, not side by side. This calls for a union [all], not a join:
SELECT name, COUNT(*)
FROM (SELECT name FROM table1
UNION ALL
SELECT name FROM table2) t
GROUP BY name

Oracle SQL Rollup Query : Determine the start of group

How can we determine the start of a Group in Rollup ?
And the include the group value by concatinating it with some useful text and display it as first row of the group ?
e.g:
dept emp_name sal
---- -------- ---
10 sac 999
10 abc 888
20 pqr 777
20 lmn 123
30 stv 444
30 com 555
o/p after rollup should be
dept emp_name sal
---- -------- ---
Department 10 NULL NULL
10 sac 999
10 abc 888
20 1887
Department 20 NULL NULL
20 pqr 777
20 lmn 123
20 900
Department 30 NULL NULL
30 stv 444
30 com 555
30 999
3786
Here is the query with which you can achieve the requirement. It uses GROUP BY ROLLUP
SELECT DISTINCT 1 AS rn,dept, CONCAT('Department ', dept) AS DeptDesc, NULL AS Sum
FROM your_table
UNION ALL
SELECT 2, dept, CAST(dept AS VARCHAR(10)), SUM(SAL)
FROM your_table
GROUP BY ROLLUP(dept, emp_name)
ORDER BY dept, rn, sum
Here is the code at SQL Fiddle