My SQL: Sum each row After Specific Row - mysql

I have a table which collects the results of football games played every week.
Based on the results of each game I input 3, 1 or 0 points for a player by ID, depending one whether they have won, drawn, or lost.
id Name A1 B1 C1 A2 B2 C2
1 C 0 3 1 3 0 0
2 G 3 0 1 3 0 0
3 k 3 0 1 0 3 3
4 S 3 0 1 N N N
5 G N N N 3 0 0
6 D N N N N N N
I'd like to be able to sum these columns, and I can do it manually by using SELECT SUM(A1+B1+C1+A2+B2+C2) FROM Results WHERE id ='1'
My issue is that each week I add an additional 2 or 3 game results - so I'd need to manually add the new games into SUM().
I thought that I would be able to use something like SUM(...) AFTER Name WHERE id = 'id'
I'm hoping I can concatenate the names of all Columns after Name and then add that into SUM(concatenatedcolumns).
But I haven't found a good example to work from yet.

You can have two tables if you do not care about 'games' metadata, I assume not as you were ready to have games listed as columns.
table:players (rows unique by id)
id name
1 A
2 B
table:scores (rows unique by combination of game_id and player_id)
game_id, player_id, score
A1 1 3
A1 2 1
B1 1 0
You can then join these two tables to get sum of scores for each players across all games
select players.id, players.name, sum(scores.score) from players inner join score
on players.id = scores.player_id group by players.id, players.name
There will not be any rows for players who did not appear in a game in 'scores' table and you do not have to deal with any null values thereby.

Related

Getting count of rows from one table where at least one related item from another table matches criteria

I have 'products' table and related 'variations' table, one product can have one or more variations. 'variations' table has 'status' column, its value can be 0 or 1. I want to get the number of products (COUNT()) which have at least one variation of status 1. How to make a query that would do that?
[EDIT]
Ok, I thought that if I simplify the question I will get away with the table structure, but, here we go (only columns relevant to the question and some mock data):
It's actually 3 linked tables:
table 1: 'products'
id
name
1
t-shirt
2
shoes
3
shorts
table 2: variations
id
product_id
1
1
2
1
3
2
4
2
5
3
6
3
7
3
table 3: stock
variation_id
quantity
status [0 or 1]
1
10
1
2
15
1
3
0
0
4
0
0
5
0
0
6
3
1
7
0
0
So, with this data, I want to know how many products there are that have at least 1 of its 'variations' of 'status' 1 - in this example it would be 2 (product 1 and 3 have some variations with status 1, product 2 does not).
You just need SUM all the quantity GROUP BY products.id with criteria is stock.status equal 1.
SELECT id, name, SUM(quantity) AS total_quantity
FROM Products pr
LEFT JOIN Variations va ON pr.id = va.product_id
LEFT JOIN Stock st ON st.variation_id = va.id
WHERE st.status = 1
GROUP BY pr.id
Join two tables and apply where filter on status column
select count(*) as cnt
from
products p
join variations v
on p.product_id = v.product_id
where status = 1

Sum within a column given two or more conditions in MySQL

In MySQL, I am trying to sum values in a column given certain conditions. I have an example of some data below
Team Season Mth Stat
A 1 1 4
A 1 1 4
A 1 2 7
A 1 2 9
B 1 1 6
B 1 1 6
B 1 2 6
B 1 2 9
C 1 1 1
C 1 1 3
C 1 2 3
C 1 2 6
But I need the output to show up as
Team Season Mth Stat
A 1 1 8
A 1 2 16
B 1 1 12
B 1 2 15
C 1 1 4
C 1 2 9
So the Stat column is now the sum of the cells such that Match, Season, and Team are all the same. I have the code below. I see a lot of answers that use 'case' but that seems to be given logical operators that are not equal to each other. When I do it below, now it doesn't recognise the table where the columns are coming from. I do have a inner joins but the data itself is from one table. I get another error as well on the sum function because it requires one argument.
select
Team
,Season
,Match
--this is where I get lost-----------
sum(
select
Stat
From
table
Where
Mth=Mth
AND Season=Season
AND Team=Team
)
--end of getting lost----------------
FROM
table
Where
Season IN (1,2)
GROUP BY
Team
,Season
,Mth
Order BY
Team ASC
Edit:
It turns out I need to use GROUP BY as the comments suggest. So I am not summing within a table, but I sum the variable given the Group By parameters.
Unless I'm missing something, it's simply:
SELECT Team
,Season
,Match
,Sum(Stat)
FROM table
GROUP BY
Team
,Season
,Match
It's simple as this:
SELECT Team,
Season,
Match,
SUM(Stat)
FROM Table
WHERE Season IN (1,2)
GROUP BY Team,
Season,
Match
ORDER BY Team ASC
Please look at the SQL Fiddle example.

Show Items even if 0 rows with group by

I'm trying to get the query below to show for each item for each store the amount of each of 4 items we have.
It works great, and I created the temporary table to try to increase speed but my problem is that if the table has no rows for a certain product that product does not show up at all.
I'd like to show all four products(prodNo) regardless of if there is actually any of rows for that specific store.
I researched this site and could not find something similar enough for me to figure it out.
CREATE TEMPORARY TABLE IF NOT EXISTS temp_invoice_dates AS
(
SELECT Invoice_detail.del_date,invoice_Detail.StoreNo,mast_stores.SDesc, invoice_Detail.ProdNo,sold_qty,retn_price,retn_qty,sold_price FROM Invoice_detail
LEFT JOIN mast_stores on invoice_detail.StoreNO=mast_stores.Snum
LEFT JOIN invoice on invoice_detail.Del_Date=invoice.Del_Date and invoice_detail.Invoice_No=invoice.Invoice_No
WHERE Cnum IN ('200','210') AND invoice_detail.Del_Date >= "2016-03-01" AND invoice_detail.Del_Date < "2016-04-01"
);
SELECT
temp_invoice_dates.StoreNo,
temp_invoice_dates.SDesc,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%Y') as Year,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%M') as Month,
temp_invoice_dates.ProdNo,
mast_items.IDesc,
SUM(sold_qty) as TotalIn,
SUM(retn_qty) as TotalOut,
ROUND(SUM((sold_qty*sold_price)-(retn_qty*retn_price)),2) as NetSales,
CONCAT(ROUND(SUM(retn_qty)/SUM(sold_qty),2)*100,'%') as StalePerc
FROM mast_Items
LEFT JOIN temp_invoice_dates on temp_invoice_dates.ProdNo=mast_items.Inum
WHERE mast_items.Inum in ('3502','3512','4162','4182')
GROUP BY temp_invoice_dates.StoreNo, ProdNo
ORDER BY temp_invoice_dates.StoreNo, ProdNo;
Drop table temp_invoice_dates;
Results are similar to:
StoreNo Product Count....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 4 4
3 2 33
3 3 3
Where as I'd like it to be
StoreNo Product Count ....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 3 0
2 4 4
3 1 0
3 2 33
3 3 3
3 4 0
Something like this should work.
SELECT sp.StoreNo, sp.ProdNo
, ...stuff...
, sp.IDesc, sp.SDesc
, ...more stuff...
FROM (
SELECT i.Inum AS ProdNo, s.Snum AS StoreNo
, i.IDesc, s.SDesc
FROM mast_Items AS i, mast_stores AS s
WHERE i.Inum IN ('3502','3512','4162','4182')
) AS sp
LEFT JOIN temp_invoice_dates AS tid
ON sp.ProdNo = tid.ProdNo
AND sp.StoreNo = tid.StoreNo
GROUP BY sp.StoreNo, sp.ProdNo
ORDER BY sp.StoreNo, sp.ProdNo
;
Normally I recommend against cross joins (as seen in the subquery) but in this case it is exactly what is needed. If the query is slow, you can instead insert the subquery results into a temp table beforehand, index that, and then use the temp table in place of the subquery.
(Edit: should use sp fields when available for grouping and results)

Sum rows after comparing one row with multiple rows

I have two tables that will be a and b. I want to compare number in a to number in b where they share an ID. a has a single row, while b has multiple. If the sum of b is less than a, then that row of a should be added to the total sum, otherwise it should be skipped.
Table a
ID Number
4 50
5 60
6 70
Table b
ID Number SharedID
1 30 4
2 25 4
3 50 5
4 5 5
5 30 6
6 10 6
Using that example: b 1 and 2 are greater than a 4, so it wouldn't be counted. b 3 and 4 are less than a 5 so it would count. b 5 and 6 are less than a 6, so it would count. The total should be 130.
I'm having trouble with doing a comparison of one row to multiple and then only summing some of the numbers.
This should do the job:
select sum(Number)
from a
where Number > (select sum(Number) from b where b.SharedID = a.ID)
Try this query:
SELECT SUM(a.Number)
FROM a INNER JOIN
(
SELECT b.SharedID, SUM(b.Number) AS theSum
FROM b
GROUP BY b.SharedID
) t
ON a.ID = t.SharedID
WHERE t.theSum < a.Number
The conceptually easiest option is to create a temporary table containing the sums of Table b, and then to JOIN that back to Table a. The WHERE clause restricts your total to only a Number values which are greater than the b sum.
select SUM(number) from(
select case when(aa.number>(select SUM(bb.number)
from bb where bb.sharedid=aa.id))then aa.number else 0 end as number from aa )abc
This should do the trick

Access Totals Query Not Necessarily Returning First Record

I have a table of data like this:
id user_id A B C
=====================
1 15 1 2 3
2 15 1 2 5
3 20 1 3 9
4 20 1 3 7
I need to remove duplicate user ids and keep the record that sorts lowest when sorting by A then B then C. So using the above table, I set up a temp query (qry_temp) that simply does the sort--first on user_id, then on A, then on B, then on C. It returns the following:
id user_id A B C
====================
1 15 1 2 3
2 15 1 2 5
4 20 1 3 7
3 20 1 3 9
Then I wrote a Totals Query based on qry_temp that just had user_id (Group By) and then id (First), and I assumed this would return the following:
user_id id
===========
15 1
20 4
But it doesn't seem to do that--instead it appears to be just returning the lowest id in a group of duplicate user ids (so I get 1 and 3 instead of 1 and 4). Shouldn't the Totals query use the order of the query it's based upon? Is there a property setting in the query that might impact this or another way to get what I need? If it helps, here is the SQL:
SELECT qry_temp.user_id, First(qry_temp.ID) AS FirstOfID
FROM qry_temp
GROUP BY qry_temp.user_id;
You need a different type of query, for example:
SELECT tmp.id,
tmp.user_id,
tmp.a,
tmp.b,
tmp.c
FROM tmp
WHERE (( ( tmp.id ) IN (SELECT TOP 1 id
FROM tmp t
WHERE t.user_id = tmp.user_id
ORDER BY t.a,
t.b,
t.c,
t.id) ));
Where tmp is the name of your table. First, Last, Min and Max are not dependent on a sort order. In relational databases, sort orders are quite ephemeral.