How to do multiple select sum sub-queries - c#

This is my first post so if I do anything incorrectly concerning the post please correct me.
I am creating a scoring program for a fishing competition.
I have the following tables(I am only going to list the columns of interest:
tblScores:
|Column Name|
Pk_CatchID
Fk_AnglerID
Day
Fk_FishID
Points
tblAnglers:
|Column Name|
Pk_AnglerID
Fk_BoatID
Name
tblBoats:
|Column Name|
Pk_BoatID
BoatName
Now what I want to do is create a score sheet for a whole week of competition, which is 5 days. So I have to do a sum of the scores and use the respective foreign keys to sum the scores for each boat.
This is what I have currently:
Select BoatName, " +
"Sum(tblScores.Points) AS [Day 1] " +
"from tblScores INNER JOIN tblAnglers ON tblScores.Fk_AnglerID=tblAnglers.Pk_AnglerID " +
" INNER JOIN tblBoats ON tblAnglers.Fk_BoatID=tblBoats.Pk_BoatID "
+ " where Day=1 GROUP BY BoatName
This works perfectly fine for one day, but what I would like to do is view this data in a DataGridView with columns for each day and then a total column as well.
Something like this:
|Boat Name|Day 1|Day 2|Day 3|Day 4|Day 5|Total|
|Example1 | 50 | 30 | 65 | 35 | 40 | 220 |
|Example2 | 40 | 50 | 70 | 35 | 30 | 225 |
I have tried using nested selects but I could not get this to work. I am open to suggestions on how this can be solved.
Also my other thought was to create a new table and keep these scores for each day in there(or even in the boats table) but I feel that the structure of the database would not be as good as data would be repeated. But I could be wrong.
Thank you all!
Also: I am using Visual Studio 2013 (C#) and Microsoft SQL Server 2010.

Try this:
Select
BoatName,
Sum(Case When Day = 1 Then tblScores.Points Else 0 End) AS [Day1],
Sum(Case When Day = 2 Then tblScores.Points Else 0 End) AS [Day2],
Sum(Case When Day = 3 Then tblScores.Points Else 0 End) AS [Day3],
Sum(Case When Day = 4 Then tblScores.Points Else 0 End) AS [Day4],
Sum(Case When Day = 5 Then tblScores.Points Else 0 End) AS [Day5],
Sum(tblScores.Points) As Total
From tblScores
INNER JOIN tblAnglers ON tblScores.Fk_AnglerID=tblAnglers.Pk_AnglerID
INNER JOIN tblBoats ON tblAnglers.Fk_BoatID=tblBoats.Pk_BoatID
GROUP BY BoatName
Order By BoatName
Fiddle

Related

Calculating change in column over groups and extracting based on criteria

I am a beginner to coding in U-SQL/C#. I am stuck in a place during windowing/aggregation.
My Data looks like
Name Date OrderNo Type Balance
one 2018-06-25T04:55:44.0020987Z 1 Drink 15
one 2018-06-25T04:57:44.0020987Z 1 Drink 70
one 2018-06-25T04:59:44.0020987Z 1 Drink 33
one 2018-06-25T04:59:49.0020987Z 1 Drink 25
two 2018-06-25T04:55:44.0020987Z 2 Drink 22
two 2018-06-25T04:57:44.0020987Z 2 Drink 81
two 2018-06-25T04:58:44.0020987Z 2 Drink 33
two 2018-06-25T04:59:44.0020987Z 2 Drink 45
In U-SQL I am adding a unique id based on combinations of name, orderno and type and for the purpose of sorting, I am adding another one including the date.
#files =
EXTRACT
name string,
date DateTime,
type string,
orderno int,
balance int
FROM
#InputFile
USING new JsonExtractor();
#files2 =
SELECT *,
DENSE_RANK() OVER(ORDER BY name,type,orderno,date) AS group_id,
DENSE_RANK() OVER(ORDER BY name,type,orderno) AS id
FROM #files;
My Data now looks like this:
Name Date OrderNo Type Balance group_id id
one 2018-06-25T04:55:44.0020987Z 1 Drink 15 1 1
one 2018-06-25T04:57:44.0020987Z 1 Drink 70 2 1
one 2018-06-25T04:59:44.0020987Z 1 Drink 33 3 1
one 2018-06-25T04:59:49.0020987Z 1 Drink 25 4 1
two 2018-06-25T04:55:44.0020987Z 2 Drink 22 5 2
two 2018-06-25T04:57:44.0020987Z 2 Drink 81 6 2
two 2018-06-25T04:58:44.0020987Z 2 Drink 33 7 2
two 2018-06-25T04:59:44.0020987Z 2 Drink 45 8 2
(I have added only 4 records per group but there are multiple per group)
I am stuck at determining the difference between successive rows in the balance column in each group.
Expected Output for Part 1:
Name Date OrderNo Type Balance group_id id increase
one 2018-06-25T04:55:44.0020987Z 1 Drink 15 1 1 0
one 2018-06-25T04:57:44.0020987Z 1 Drink 70 2 1 55
one 2018-06-25T04:59:44.0020987Z 1 Drink 33 3 1 -37
one 2018-06-25T04:59:49.0020987Z 1 Drink 25 4 1 -8
two 2018-06-25T04:55:44.0020987Z 2 Drink 22 5 2 0
two 2018-06-25T04:57:44.0020987Z 2 Drink 81 6 2 59
two 2018-06-25T04:58:44.0020987Z 2 Drink 33 7 2 -48
two 2018-06-25T04:59:44.0020987Z 2 Drink 45 8 2 8
For every new group (defined by id) the increase should start from zero.
I went through stack overflow and saw the lag function from transgresql. I could not find a C# equivalent. Is that applicable in this case?
Any help is appreciated. Further clarification will be provided if required.
Update: When I use CASE WHEN my solution looks like this
CURRENT OUTPUT DESIRED OUTPUT
id Balance Increase id Balance Increase
1 15 0 1 15 0
1 70 55 1 70 55
1 33 -37 1 33 -37
1 25 -8 1 25 -8
2 22 "-3" 2 22 "0"
2 81 59 2 81 59
2 33 -48 2 33 -48
2 45 12 2 45 12
Look at the highlighted row. The increase column must start at 0 for each id.
Update: I was able to solve the first part of my question. See my answer below.
The second part that I had posted earlier was incorrectly posted. I have removed that.
You can try to use LAG window function get previous Balance in a subquery, then use where write the condition.
SELECT * FROM (
SELECT *,
DENSE_RANK() OVER(ORDER BY name,type,orderno,date) AS group_id,
DENSE_RANK() OVER(ORDER BY name,type,orderno) AS id,
(CASE WHEN LAG(Balance) OVER(ORDER BY name,type,orderno) IS NULL THEN 0
ELSE Balance - LAG(Balance) OVER(ORDER BY name,type,orderno)
END) as increase
FROM #files
) t1
WHERE increase > 50
The query that finally worked for me was this..
#files =
EXTRACT
name string,
date DateTime,
type string,
orderno int,
balance int
FROM
#InputFile
USING new JsonExtractor();
#files2 =
SELECT *,
DENSE_RANK() OVER(ORDER BY name,type,orderno) AS group_id
FROM #files;
#files3 =
SELECT *,
DENSE_RANK() OVER(PARTITION BY group_id ORDER BY date) AS group_order
FROM #files2;
#files4 =
SELECT *,
(CASE WHEN group_order == 1 THEN 0
ELSE balance - LAG(balance) OVER(ORDER BY name,type,orderno)
END) AS increase
FROM #files3;

SQL string concatenation based on field value

I am wondering if there is a straightforward way of concatenating a string based on the value of a field directly in SQL. I know it would be preferable to do in an application, but in this instance, I am only able to use SQL. For example, the following table:
Labels | Qty | LabelQty | OutputString
-------+-----+----------+--------------
1 | 30 | 30 | NULL
2 | 60 | 30 | NULL
2 | 120 | 60 | NULL
I would like to end up with the OutputString like so:
Labels | Qty | LabelQty | OutputString
-------+-----+----------+--------------
1 | 30 | 30 | 30|
2 | 60 | 30 | 30|30|
2 | 120 | 60 | 60|60|
I know this is very easy to do in C# or VB, but I am having a hard time thinking about how to accomplish this in straight SQL. Would I need to use a cursor and do each row one at a time? Unfortunately, I can't just use the string multiplier like in Ruby, such as:
SELECT (CONVERT(VARCHAR(10), LabelQty) + '|') * Labels
Any pointers are much appreciated.
You can use REPLICATE() function:
select replicate(cast(LabelQty as varchar(100)) + '|', Labels)
from mytable_1
You can try
SELECT REPLICATE(CONVERT(VARCHAR(10), LabelQty ) + '|',Labels )
While you haven't described how to produce output string, but I think that this can be done with case expression:
http://technet.microsoft.com/en-us/library/ms181765.aspx
And sample from that article:
SELECT ProductNumber, Name, "Price Range" =
CASE
WHEN ListPrice = 0 THEN 'Mfg item - not for resale'
WHEN ListPrice < 50 THEN 'Under $50'
WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
ELSE 'Over $1000'
END
FROM Production.Product
ORDER BY ProductNumber ;

How can i get the sum of a database table to a variable?

I have a database table named Deposit and one of the column name in it is 30-12-2013. The column has two values such as 54,26.
i want to get the sum of that column column into a variable. I use the following code:
con.Open();
SqlCeCommand cmd11 = con.CreateCommand();
cmd11.CommandText = "select sum(30-12-2013) from Deposit";
int result = ((int)cmd11.ExecuteScalar());
displaylabel.Text = result.ToString();
con.Close();
But, I am getting the value of variable 'result' as -3990.
Whats wrong with my code.. Please help me.. Thanks in advance..
(30-12-2013) * 2 (because you have two entries) = -1995 * 2 = -3990
You have to use:
SELECT sum([30-12-2013])
FROM dbo.Deposit
This has already been answered so instead of answering your actual question I am going to propose an alternative solution.
Instead of having a table as follows:
SomeColumn | 30-12-2013 | 31-12-2013 | 01-01-2014
-----------+------------+------------+------------
A | 540 | 100 | 246
B | 130 | 90 | 377
Have a normalised table:
SomeColumn | Date | Amount
-----------+------------+--------
A | 2013-12-30 | 540
A | 2013-12-31 | 100
A | 2014-01-01 | 246
B | 2013-12-30 | 130
B | 2013-12-31 | 90
B | 2014-01-01 | 377
This means you don't require a new column for every day. So your query would become:
SELECT SUM(Amount) AS Amount
FROM Deposit
WHERE Date = '20131230';
And if you wanted to reproduce your original structure you can use:
SELECT SomeColumn,
SUM(CASE WHEN Date = '20131230' THEN Amount ELSE 0 END) AS [30-12-2013],
SUM(CASE WHEN Date = '20131231' THEN Amount ELSE 0 END) AS [31-12-2013],
SUM(CASE WHEN Date = '20140101' THEN Amount ELSE 0 END) AS [01-01-2014]
FROM Deposit
GROUP BY SomeColumn;
Example on SQL Fiddle (Using SQL Server as it doesn't support SQL Server CE)
Try to use brackets for columns with unusual names -
cmd11.CommandText = "SELECT SUM([30-12-2013]) FROM Deposit";

how to dynamically create multiple select statement and store it in a datatable

the case here is the number of columns i would like to store to the datatable depends on the number of available data. i would need a multiple select statements to collect all the data.
select test_result.stud_id,test_info.max_score,
test_result.test_score
from test_result left join test_info
on test_result.test_info_id = test_info.test_info_id
where test_info.test_type_id = 1 and test_info.test_num = 1;
i would have to repeat this code over and over again until the test_num reaches the current maximum count. i was thinking of looping this code while storing it to the datatable.this is what i would like the datagridview would display.
|Quiz Number | Quiz#1 | Quiz #2 | Quiz #3 | Quiz #4 | Quiz #5 |
|Max score | 20 | 25 | 30 | 15 | 15 |
|student 1 | 18 | 22 | 25 | 12 | 14 |
|student 2 | 19 | 20 | 25 | 11 | 13 |
|student 3 | 20 | 24 | 20 | 12 | 11 |
the display of data would be in rows. so each row would require a different select statement in order to display the required data.
Something like below will woek for you
select
test_result.stud_id,
max(case when test_result.test_info_id =1 then test_result.test_score end) as quiz_1,
max(case when test_result.test_info_id =2 then test_result.test_score end) as quiz_2,
max(case when test_result.test_info_id =3 then test_result.test_score end) as quiz_3,
.
.
.
from test_result left join test_info
on test_result.test_info_id = test_info.test_info_id
where test_info.test_type_id = 1 and test_info.test_num = 1
group by test_result.stud_id;

Analytical TSQL

I need to produce some SQL that will show me the trend (up or down tick) in some transacitons.
Consider this table with a PlayerId and a Score
PlayerId, Score, Date
1,10,3/13
1,11,3/14
1,12,3/15
If I pull data from 3/15 I have a score of 12 with an upward trend compared to the historical data.
I did something similar in Oracle 8i about 10 years ago using some of the analytical functions like rank, however it was 10 years ago....
The results would look similar to
PlayerId, Score, Date, Trend
1,12,3/15,UP
How can I do something similar with sql azure?
This SQL:
with data as (
select * from ( values
(1,11,cast('2013/03/12' as smalldatetime)),
(1,15,cast('2013/03/13' as smalldatetime)),
(1,11,cast('2013/03/14' as smalldatetime)),
(1,12,cast('2013/03/15' as smalldatetime))
) data(PlayerId,Score,[Date])
)
select
this.*,
Prev = isnull(prev.Score,0),
tick = case when this.Score > isnull(prev.Score,0) then 'Up' else 'Down' end
from data this
left join data prev
on prev.PlayerId = this.PlayerId
and prev.[Date] = this.[Date] - 1
returns this output:
PlayerId Score Date Prev tick
----------- ----------- ----------------------- ----------- ----
1 11 2013-03-12 00:00:00 0 Up
1 15 2013-03-13 00:00:00 11 Up
1 11 2013-03-14 00:00:00 15 Down
1 12 2013-03-15 00:00:00 11 Up

Categories

Resources