SQL Sum a Sum, or combine - sql

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

Related

nesting multiple queries in 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;

SQL query issue COUNT()

I tried set the count of rows which have a specific value for multiple columns in the same query
this is what I have tried...
SELECT
COUNT(*) AS house_with_12_rooms,
COUNT(*) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms = "twelve"
OR num_of_rooms = "four"
since there are 157 rows with houses with 12 rooms and 1 row with houses with 4 rooms the result adds up the counts in the result table RATHER THAN placing 157 and 1 respectively.
Row house_with_12_rooms house_with_4_rooms
1 158 158
Could someone give me a clue on how to set up the query properly?
Use conditional aggregation:
SELECT SUM(CASE WHEN num_of_rooms = 'twelve' THEN 1 ELSE 0 END) AS house_with_12_rooms,
SUM(CASE WHEN num_of_rooms = 'four' THEN 1 ELSE 0 END) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms IN ('twelve', 'four')

SQL: alternatives and substitutions for GROUPING SETS and PIVOT

I've got code like this:
SELECT id, YEAR(datek) AS YEAR, COUNT(*) AS NUM
FROM Orders
GROUP BY GROUPING SETS
(
(id, YEAR(datek)),
id,
YEAR(datek),
()
);
It gives me this output:
1 NULL 4
2 NULL 11
3 NULL 6
NULL NULL 21
1 2006 36
2 2006 56
3 2006 51
NULL 2006 143
1 2007 130
2 2007 143
3 2007 125
NULL 2007 398
1 2008 79
2 2008 116
3 2008 73
NULL 2008 268
NULL NULL 830
1 NULL 249
2 NULL 326
3 NULL 255
What I need to do is write it without "grouping sets" (nor cube or rollup) but with the same result. I thought about writing three different queries and join them with "union". I try something like "null" in group by settings but it does not work.
SELECT id, YEAR(datek) AS rok, COUNT(*) AS NUM
FROM Orders
GROUP BY id, YEAR(datek)
UNION
SELECT id, YEAR(datek) AS rok, COUNT(*) AS NUM
FROM Orders
GROUP BY id, null
order by id, YEAR(datek)
I also have a question about "PIVOT". What kind of syntax can replace query with "PIVOT"?
Thanks for your time and all the answers!
You are right in that you need separate queries, although you actually need 4, and rather than GROUP BY NULL, just group by the columns in the corresponding grouping set, and replace the column in the SELECT with NULL:
SELECT id, YEAR(datek) AS rok, COUNT(*) AS NUM
FROM Orders
GROUP BY id, YEAR(datek)
UNION ALL
SELECT id, NULL, COUNT(*) AS NUM
FROM Orders
GROUP BY id
UNION ALL
SELECT NULL, YEAR(datek), COUNT(*) AS NUM
FROM Orders
GROUP BY YEAR(datek)
UNION ALL
SELECT NULL, NULL, COUNT(*) AS NUM
FROM Orders
ORDER BY ID, Rok
With regard to a replacement for PIVOT I think the best alternative is to use a conditional aggregate, e.g. instead of:
SELECT pvt.SomeGroup,
pvt.[A],
pvt.[B],
pvt.[C]
FROM T
PIVOT (SUM(Val) FOR Col IN ([A], [B], [C])) AS pvt;
You would use:
SELECT T.SomeGroup,
[A] = SUM(CASE WHEN T.Col = 'A' THEN T.Val ELSE 0 END),
[B] = SUM(CASE WHEN T.Col = 'B' THEN T.Val ELSE 0 END),
[C] = SUM(CASE WHEN T.Col = 'C' THEN T.Val ELSE 0 END)
FROM T
GROUP BY T.SomeGroup;

Oracle database subquery results in multiple rows

Hi am having an SQL problem, and I hope the answer is pretty easy.
I have a database with the following structure.
State Gender birthyear birthname count
----- ------ --------- --------- ------
AK F 1923 Helen 15
AK F 1926 Helen 35
AK F 1927 Susan 25
AK F 1920 Helen 15
There are thousands of records and I would like the output to look like this:
birthname 1910 1911 1912 -->2012
----- ------ --------- --------- ------
Helen 5 6 12 800
Using MS Access I was able to get some results with this:
SELECT DISTINCT as1.birthname AS Expr1,
(select totalcount from AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=1910) as 1910,
(select totalcount from AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=1911) as 1911,
(select totalcount from AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=2012) as 2012
FROM AK AS as1
You should do this using conditional aggregation:
SELECT as1.birthname AS Expr1,
SUM(case when birthyear = 1910 then `count` else 0 end) as yr_1910,
SUM(case when birthyear = 1911 then `count` else 0 end) as yr_1911,
SUM(case when birthyear = 1912 then `count` else 0 end) as yr_1912
FROM AK AS as1
GROUP BY as1.birthname;
I am not sure where gender and state come in. These are not included in the outer query, which is probably the cause of your syntax error. You might want to include these in the aggregation:
SELECT as1.birthname, as1.gender, as1.state,
SUM(case when birthyear = 1910 then `count` else 0 end) as yr_1910,
SUM(case when birthyear = 1911 then `count` else 0 end) as yr_1911,
SUM(case when birthyear = 1912 then `count` else 0 end) as yr_1912
FROM AK AS as1
GROUP BY as1.birthname, as1.gender, as1.state;
If you are using Oracle 11g+ you can use the SQL PIVOT syntax to generate a crosstab report. With sample data the query would be something like this:
with sample_data as
(select 'AK' state, 'F' gender, 1923 birthyear, 'Helen' birthname, 15 namecount from dual union all
select 'AK', 'F', 1926, 'Helen', 35 from dual union all
select 'AK', 'F', 1927, 'Susan', 25 from dual union all
select 'AK', 'F', 1920, 'Helen', 15 from dual)
select * from (
select * from sample_data
)
pivot
(
sum(namecount)
for birthyear in (1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1230)
);
Unfortunately the list of years in the IN clause must be hardcoded, you cannot generate that list dynamically with a subquery. However, that should be not be too hard to initially populate.

How to transpose recordset columns into rows

I have a query whose code looks like this:
SELECT DocumentID, ComplexSubquery1 ... ComplexSubquery5
FROM Document
WHERE ...
ComplexSubquery are all numerical fields that are calculated using, duh, complex subqueries.
I would like to use this query as a subquery to a query that generates a summary like the following one:
Field DocumentCount Total
1 dc1 s1
2 dc2 s2
3 dc3 s3
4 dc4 s4
5 dc5 s5
Where:
dc<n> = SUM(CASE WHEN ComplexSubquery<n> > 0 THEN 1 END)
s <n> = SUM(CASE WHEN Field = n THEN ComplexSubquery<n> END)
How could I do that in SQL Server?
NOTE: I know I could avoid the problem by discarding the original query and using unions:
SELECT '1' AS TypeID,
SUM(CASE WHEN ComplexSubquery1 > 0 THEN 1 END) AS DocumentCount
SUM(ComplexSubquery1) AS Total
FROM (SELECT DocumentID, BLARGH ... AS ComplexSubquery1) T
UNION ALL
SELECT '2' AS TypeID,
SUM(CASE WHEN ComplexSubquery2 > 0 THEN 1 END) AS DocumentCount
SUM(ComplexSubquery2) AS Total
FROM (SELECT DocumentID, BLARGH ... AS ComplexSubquery2) T
UNION ALL
...
But I want to avoid this route, because redundant code makes my eyes bleed. (Besides, there is a real possibility that the number of complex subqueries grow in the future.)
WITH Document(DocumentID, Field) As
(
SELECT 1, 1 union all
SELECT 2, 1 union all
SELECT 3, 2 union all
SELECT 4, 3 union all
SELECT 5, 4 union all
SELECT 6, 5 union all
SELECT 7, 5
), CTE AS
(
SELECT DocumentID,
Field,
(select 10) As ComplexSubquery1,
(select 20) as ComplexSubquery2,
(select 30) As ComplexSubquery3,
(select 40) as ComplexSubquery4,
(select 50) as ComplexSubquery5
FROM Document
)
SELECT Field,
SUM(CASE WHEN RIGHT(Query,1) = Field AND QueryValue > 1 THEN 1 END ) AS DocumentCount,
SUM(CASE WHEN RIGHT(Query,1) = Field THEN QueryValue END ) AS Total
FROM CTE
UNPIVOT (QueryValue FOR Query IN
(ComplexSubquery1, ComplexSubquery2, ComplexSubquery3,
ComplexSubquery4, ComplexSubquery5)
)AS unpvt
GROUP BY Field
Returns
Field DocumentCount Total
----------- ------------- -----------
1 2 20
2 1 20
3 1 30
4 1 40
5 2 100
I'm not 100% positive from your example, but perhaps the PIVOT operator will help you out here? I think if you selected your original query into a temporary table, you could pivot on the document ID and get the sums for the other queries.
I don't have much experience with it though, so I'm not sure how complex you can get with your subqueries - you might have to break it down.