nesting multiple queries in SQL - sql

I want to know in the year in which more goals were scored (in total), how many goals were scored by and against team 1 when team 1 is either a or b.
My table looks like this:
year
team1
team2
score_team1
score_team2
1
a
x
10
5
1
b
y
4
3
2
a
z
2
7
2
a
x
9
6
2
b
z
0
7
This is the output that I need:
year
team
max_score_team1
max_score_team2
2
a
11
13
2
b
0
7
I know that more goals were scored in year 2 by doing this query:
select year, sum(score_team1 + score_team2) as total
from data
group by year
order by sum(score_team1 + score_team2) desc
limit(1)
Now I want to know how many goals were scored by and against team1 when team1 is either a or b. I know how to write the queries separately but how can I nest them in one query so I can get the results in one table like the one above?

To obtain the results you desire in a single table, you can use a SQL query with a GROUP BY clause and a HAVING clause to filter for the year in which the most goals were scored. If you are using MySQL, the query might look something like this:
SELECT year, team1,
SUM(score_team1) AS max_score_team1,
SUM(score_team2) AS max_score_team2
FROM data
GROUP BY year, team1
HAVING year = (SELECT year
FROM data
GROUP BY year
ORDER BY SUM(score_team1 + score_team2) DESC
LIMIT 1)
AND team1 IN ('a', 'b')
The GROUP BY clause groups the results by year and team, and the HAVING clause is used to filter only the results for the year in which the most goals were scored and for team 'a' or 'b'. The nested query in the HAVING clause is used to obtain the year in which the most goals were scored.
The result of the query would be something like this:
year
team1
max_score_team1
max_score_team2
2
a
11
13
2
b
0
7

Use conditional aggregation to count team #1's goals.
select
year,
sum(score_team1 + score_team2) as total,
sum(case when team1 = 1 then score_team1 else 0 end) +
sum(case when team2 = 1 then score_team2 else 0 end) as scored_by_team_1,
sum(case when team1 = 1 then score_team2 else 0 end) +
sum(case when team2 = 1 then score_team1 else 0 end) as scored_against_team_1
from data
group by year
order by total desc
limit 1;
The problem with that: If there is more than one year with the top goals count, you'd pick one arbitrarily.
So, instead:
select year, total, scored_by_team_1, scored_against_team_1
from
(
select
year,
sum(score_team1 + score_team2) as total,
max(sum(score_team1 + score_team2)) over () as max_total,
sum(case when team1 = 1 then score_team1 else 0 end) +
sum(case when team2 = 1 then score_team2 else 0 end) as scored_by_team_1,
sum(case when team1 = 1 then score_team2 else 0 end) +
sum(case when team2 = 1 then score_team1 else 0 end) as scored_against_team_1
from data
group by year
) with_max_total
where total = max_total;

Related

Sqlite group by distinct count

I have table of customers operations:
date, client_id, gender
1 1 M
1 1 M
1 2 M
1 2 M
1 3 F
2 1 M
2 1 M
2 1 M
2 2 M
2 2 M
2 3 F
2 3 F
2 4 F
2 5 M
2 5 M
etc
Desired output is:
date, amount of males, (also need amount of females)
1 2 1
2 3 2
I need to group it by date, so i did it, then my goal is to find amount of each gender in each grouped group.
so i tried to do this to count amount of males:
sum(case when gender = 'M' then 1 else NULL end) as 'M%'
but its counted clients id 1 and 2 two times each, but i need to count it distinct.
On example above i expect this to return 2 because 2 male. But it return 4 because distinct construction doesnt work.
I tried this but it doesnt work and count '1' in result:
sum(distinct case when gender = 'M' then 1 else NULL end) as 'M%'
It's easier to count from the distinct rows of the table.
Also, use SQLite's feature to treat boolean expressions as 1 for true and 0 for false so you can sum them instead of using CASE expressions:
SELECT date,
SUM(gender = 'M') [amount of males],
SUM(gender = 'F') [amount of females]
FROM (SELECT DISTINCT date, client_id, gender FROM tablename)
GROUP BY date
See the demo.
You seem to want conditional count(distinct):
select date,
count(distinct case when gender = 'M' then client_id end) as count_m,
count(distinct case when gender = 'F' then client_id end) as count_f
from t
group by date;

SQL Sum a Sum, or combine

i need help with the following query it should produce a sum of all the goals made in every match played:
SELECT SUM(stand1)
FROM wedstrijdmodule_wedstrijden
WHERE team1 = 25
UNION
SELECT SUM(stand2)
FROM wedstrijdmodule_wedstrijden
WHERE team2 = 25;
it results in:
SUM(stand1)
68
77
I need:
SUM(stand1)
145
It's been a while since I did SQL and searched for about an hour, with no results. It doesn't have to look pritty because it will be extracted using php.
Simple answer, wrap your query up in a derived table and do another SUM:
select sum(sm)
from
(
SELECT SUM(stand1) as sm
FROM wedstrijdmodule_wedstrijden
WHERE team1 = 25
UNION ALL
SELECT SUM(stand2)
FROM wedstrijdmodule_wedstrijden
WHERE team2 = 25
) dt
Switched to UNION ALL, in case the two select returns same number.
Or, use case expressions to do conditional aggregation:
SELECT SUM(case when team1 = 25 then stand1 else 0 end) +
SUM(case when team2 = 25 then stand2 else 0 end)
FROM wedstrijdmodule_wedstrijden
WHERE team1 = 25 or team2 = 25

SQL to calculate Net Capacity

How to write a SQL to get the Net change in capacity by using the capacity (when status is 1 or 2) and minus the total capacity (when status is 3) for each month? Thanks. Here is the table:
STATUS MONTH CAPACITY
1 01/16 5
3 01/16 2
1 02/16 11
3 02/16 20
1 03/16 8
3 03/16 12
1 04/16 4
2 04/16 10
3 04/16 18
2 05/16 14
3 05/16 37
2 06/16 4
3 06/16 8
For example, the net change in capacity for Jan. 16 is 5 minus 2 equals 3.
You need a conditional sum:
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY ELSE 0 END) -
SUM(CASE WHEN STATUS IN (3) THEN CAPACITY ELSE 0 END)
dnoeth answer can be simplified to
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY WHEN STATUS IN (3) THEN -CAPACITY ELSE 0 END)
Builds on 1,2 < 3
select MONTH, [Net change]=SUM(CASE STATUS/3 WHEN 0 THEN CAPACITY ELSE -CAPACITY END)
from t
group by MONTH;
no CASE statement:
select month, sum(capacity)-2*sum((status/3)*capacity) from table group by month;
Here is an example
You can join the table to itself and perform the calculation like so:
SELECT
a.status,
a.month,
a.capacity,
b.capacity AS total_capacity,
a.capacity - b.capacity AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2);
-- If you don't want to have the status and instead aggregate in the event there are two within the same month:
SELECT
a.month,
SUM(a.capacity) AS capacity,
SUM(b.capacity) AS total_capacity,
SUM(a.capacity) - MAX(b.capacity) AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2)
GROUP BY
a.month;
SELECT
"Status",
"Month",
SUM(Capacity) AS Capacity
FROM ( SELECT
"Status",
"Month",
CASE WHEN Status = 3 THEN -1 * Capacity ELSE Capacity END AS Capacity FROM tbl
) t
GROUP BY
"Status",
"Month"

Count Values from Table for each type

I have the following table
UserId [nvarchar(128)], Rating [varchar(170)] :values will be mostly 1,2,3 but can have exceptions
Rating contains 3 values [1,2, or 3]
I want to get a result something like
UserId Count(1's),Count(2's) Count(3's)
1. 1001 10 8 2
2. 1002 5 10 3
Is it possible in a single query
Do a GROUP BY UserId to count for each user-id. Use CASE to count 1's, 2's and 3's separately:
select UserId,
count(case when Rating = 1 then 1 end) as [Count(1's)],
count(case when Rating = 2 then 1 end) as [Count(2's)],
count(case when Rating = 3 then 1 end) as [Count(3's)]
from tablename
group by UserId
Use a CASE statement in each COUNT and then GROUP BY UserId.
SELECT UserId, COUNT(CASE WHEN value = '1' THEN 1 END) AS [Count(1's)], COUNT(CASE WHEN value = '2' THEN 1 END) AS [Count(2's)], COUNT(CASE WHEN value = '3' THEN 1 END) AS [Count(3's)]
FROM yourtable
GROUP BY UserId
Use PIVOT:
SELECT
UserId,
COALESCE([1],0) [Count(1's)],
COALESCE([2],0) [Count(2's)],
COALESCE([3],0) [Count(3's)]
FROM
ýour_table
PIVOT
(COUNT([Rating])
FOR Rating
in([1],[2],[3])
)AS p
ORDER BY
UserId

SQL Query to fetch employee Attendence

I need to write query on employee table to fetch the employee with employee ID & how many days he is present absent & half-day for given date range.
Employee
AID EmpID Status Date
1 10 Present 17-03-2015
2 10 Absent 18-03-2015
3 10 HalfDay 19-03-2015
4 10 Present 20-03-2015
5 11 Present 21-03-2015
6 11 Absent 22-03-2015
7 11 HalfDay 23-03-2015
Expected Output will be :
EmpID Present Absent HalfDay
10 2 1 1
11 1 1 1
Can you please help me with the Sql query ?
Here Is the query I tried
SELECT EMP.EMPID,
(CASE WHEN EMP.STATUS = 'Present' THEN COUNT(STATUS) ELSE 0 END) Pres,
(CASE WHEN EMP.STATUS = 'Absent' THEN COUNT(STATUS) ELSE 0 END) ABSENT,
(CASE WHEN emp.status = 'HalfDay' THEN Count(status) ELSE 0 END) HalfDay
FROM EMPLOYEE EMP GROUP BY emp.empid
The COUNT() function tests if the value is NOT NULL. Therefore it will always increment for both sides of a CASE statement like this:
COUNT(CASE Status WHEN 'Present' THEN 1 ELSE 0) AS Present
So we need to use SUM() ...
select empid,
sum(case when status='Present' then 1 else 0 end) present_tot,
sum(case when status='Absent' then 1 else 0 end) absent_tot,
sum(case when status='HalfDay' then 1 else 0 end) halfday_tot
from employee
group by empid
order by empid
/
... or use COUNT() with a NULL else clause. Both produce the same output, perhaps this one is clearer:
SQL> select empid,
2 count(case when status='Present' then 1 end) present_tot,
3 count(case when status='Absent' then 1 end) absent_tot,
4 count(case when status='HalfDay' then 1 end) halfday_tot
5 from employee
6 group by empid
7 order by empid
8 /
EMPID PRESENT_TOT ABSENT_TOT HALFDAY_TOT
---------- ----------- ---------- -----------
10 2 1 1
11 1 1 1
SQL>
Note that we need to use ORDER BY to guarantee the order of the result set. Oracle introduced a hashing optimization for aggregations in 10g which meant GROUP BY rarely returns a predictable sort order.
Replace 0 with null because it would be also come in count and added the where clause for date range, check the example below:
select empID,
count(case when status='Present' then 1 else null end) Present_Days,
count(case when status='Absent' then 1 else null end) Absent_Days,
count(case when status='HalfDay' then 1 else null end) HalfDays
from Employee
where date >= to_date('17mar2015') and date <= to_date('23mar2015')
group by empID