SQLite Find amount of stocks using data from different tables - database

I have the following data structure shown in the picture and the task is to find the number of shares for each client.
In the table deals, I have a column called euro_amount which has positive numbers if the client has sold some stocks or negative in case of buying.
I have to calculate the total number of shares the client holds.
My idea was to group deals by clients, then for every deal separately check if the euro_amount is positive, if yes then divide by sell_price(get a positive number), else divide buy buy_price(get a negative number) (from table prices). Then sum up the total amount of stocks.
But I am struggling with implementing it.
What I have tried is:
select *,
case when d.euro_amount<0 then (d.euro_amount/p.buy_price) as stock_in
else (d.euro_amount/p.sell_price) as stock_out
(stock_in+stock_out) as sum
inner join prices p on p.id_price=d.id_price
end
from table deals d
group by d.id_client;
I am getting an error: Error: near "as": syntax error

Join the 3 tables, group by client and aggregate with a CASE expression that meets your requirement:
select c.id_client, c.first_name, c.last_name,
sum(d.euro_amount / case when d.euro_amount > 0 then p.sell_price else p.buy_price end) totalsum
from clients c
left join deals d on d.id_client = c.id_client
left join prices p on p.id_price = d.id_price
group by c.id_client, c.first_name, c.last_name
To avoid integer division, if the columns euro_amount, sellprice and buy_price are integers, use this:
sum(1.0 * d.euro_amount / case when d.euro_amount > 0 then p.sell_price else p.buy_price end) totalsum

Related

Average of a player

I have a record that contains stat for a certain cricket player.
It has columns having dates, oppositions, Runs, Balls, Dismissals, Match_Number.
I want to do a query (SQL SERVER) to find out the batting average where every runs (Sum) is to be added; innings having a count of all innings except DNB but dismissal should not have a count of "Not Out", "Retired Hurt", "DNB" grouped by the opposition.
Note : DNB means Did not Bat.
The query doesn't have the required number of innings to calculate the average
So the problem is can't gather information for a single entity (count of no. of innings) having two set of parameters.
Without DNB
Without DNB, Not Out, Retired Hurt.
Please suggest.
You can put a case expression within an aggregate to exclude certain rows from a count/sum/average etc. So you could use something like this:
SELECT a.Opposition,
Matches = COUNT(*),
Innings = COUNT(CASE WHEN a.Dismissal <> 'DNB' THEN 1 END),
Runs = SUM(a.Runs),
Average = SUM(a.Runs) / NULLIF(COUNT(CASE WHEN a.Dismissal NOT IN ('DNB', 'Not Out', 'Retired not out') THEN 1 END), 0)
FROM dbo.SRTundlkarODI AS a
GROUP BY a.Opposition;
N.B. I have wrapped the COUNT for the average in NULLIF(<exp>, 0) so that should the batsmen have never got out you avoid a divide by zero error.

How do I nest if then statements with select statements including other if then statements?

I'm fairly new to SQL and can't figure out how to combine several if .. then statements.
What is the right syntax for this?
I'm using SQL Server Management Studio 2017.
I've tried to combine if... else if..statements and I tried using case statements, but I always get lost in the nesting of the statements.
I have several condtions whom have to be met before I can execute some sort of calculation.
It should be something like this:
If CalculationMethod = x
and if (Price * coefficient) < Amount
then CalculatedAmount = Amount
else CalculatedAmount = (Price * coefficient)
Where Amount has it's own if statements:
Amount =
If Category = a and DistanceFrom <= Distance >= DistanceUntill then take amount from that particular cell
If Category = b and DistanceFrom <= Distance >= DistanceUntill then take amount from that particular cell
If Category = c and DistanceFrom <= Distance >= DistanceUntill then take amount from that particular cell
In this case, Amount is a cell in a table with columns DistanceFrom, DistanceUntill, a, b and c.
CalculationMethod and Coefficient are columns in another table.
Price is a column in third table.
In the end I want the CalculatedAmount based on the Amount, Price and Coefficient.
Does this make any sense? Does anyone has an idea on how to tackle this?
If you have an IF...THEN...ELSE type of scenario I think the right direction would be to use a CASE statement such as:
SELECT CASE WHEN CalculationMethod = x AND ((Price * coefficient) < Amount) THEN Amount
ELSE (Price * coefficient) END CalculatedAmount
You can read about it here: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017
An IIF clause works very well when there is only one decision branch, but if you have multiple things to choose from the CASE statement is the way to go.
SELECT IIF(CalculationMethod = x and Price * coefficient < Amount, Amount, Price * coefficient) as CalculatedAmount
FROM aTable

Performing COUNT() on a computed Column from a VIEW

So all I want to do is have a view that shows how many kid between and including the age of 5 - 18 are in each family. I AM USING SQL SERVER.
The view I Have written to get the Family Members Ages is
CREATE VIEW VActiveMembers
AS
SELECT
TM.intMemberID AS intMemberID,
TM.strFirstName AS strFirstName,
TM.strLastName AS strLastName,
TM.strEmailAddress AS strEmailAddress,
TM.dtmDateOfBirth AS dtmDateOfBirth,
FLOOR(DATEDIFF(DAY, dtmDateOfBirth, GETDATE()) / 365.25) AS intMemberAge
FROM
TMembers AS TM
WHERE
TM.intStatusFlagID = 1
intStatusFlag = 1 is just a flag that means the member is active.
Now I have tried for about 3ish hours to figure this out but I cannot figure it out. Here is the one where instead of trying to get the solution in one fowl swoop I tried to step wise it, but then I still didn't get the result I wanted.
As you can see I didn't use the view where I calculated the AGE from because the "Multi-part Identifier could not be bound" I have seen that error but I couldn't get it to go away in this case. Ideally I would like the count to be performed on the VIEW instead of recalculating the ages all over again
CREATE VIEW VActiveFamilyMembersK12Count
AS
SELECT
TF.intParishFamilyID,
COUNT(DATEDIFF(DAY, dtmDateOfBirth, GETDATE()) / 365) AS intMemberAgeCount
FROM
TFamilies AS TF
INNER JOIN
TFamilyMembers AS TFM
INNER JOIN
VActiveMembers AS vAM ON (TFM.intMemberID = vAM.intMemberID)
ON (TFM.intParishFamilyID = TF.intParishFamilyID)
WHERE
TF.intStatusFlagID = 1
GROUP BY
TF.intParishFamilyID
I wanted to just get a count using the age calculation just to see If I could get a correct count of members in a family, then I could start building upon that to get a count of members of a certain age. The result I get back is 2 but there are guaranteed 3 members to each family.
The result I am looking For is this
Family_ID | K12Count
-----------------------------
1001 | 2
1002 | 0
1003 | 1
1004 | 0
Here is a list of resources I looked up trying to figure this out, maybe one of them is in fact the answer and I just don't see it, but I am at a loss at the moment.
SQL Select Count from below a certain age
How to get count of people based on age groups using SQL query in Oracle database?
Count number of user in a certain age's range base on date of birth
Conditional Count on a field
http://timmurphy.org/2010/10/10/conditional-count-in-sql/
*** EDIT ***
CREATE VIEW VActiveFamilyMembersK12Count
AS
SELECT
TF.intParishFamilyID,
SUM(CASE WHEN intMemberAge >= 5 AND intMemberAge <= 18 THEN 1 ELSE 0 END) AS intK12Count
FROM
TFamilies AS TF
INNER JOIN TFamilyMembers AS TFM
INNER JOIN VActiveMembers AS vAM
ON (TFM.intMemberID = vAM.intMemberID)
ON (TFM.intParishFamilyID = TF.intParishFamilyID)
WHERE
TF. intStatusFlagID = 1
GROUP BY
TF.intParishFamilyID
GO
THIS IS THE SOLUTION ABOVE.
Conditional count is the way to go.
Something like:
SELECT intParishFamilyID,
COUNT(CASE WHEN intMemberAge >=5 and intMemberAge <=18 THEN 1 ELSE 0 END)
FROM
TFamilies AS TF
INNER JOIN TFamilyMembers AS TFM
INNER JOIN VActiveMembers AS vAM
ON (TFM.intMemberID = vAM.intMemberID)
ON (TFM.intParishFamilyID = TF.intParishFamilyID)
WHERE
TF. intStatusFlagID = 1
GROUP BY
TF.intParishFamilyID

T-SQL : Cannot perform an aggregate function on an expression containing an aggregate or a subquery

I am trying to add the result of the total of some amount and substract it to the total but i see the following error:
Imagine something like this
First Subquery : 1 3 5 7
Second Subquery : 2 4 6
Total : (1+3+5+7) - (2+4+6) = 4
This is my query but as I said i see the following error:
Select SUM ((
(select SUM (amount) FROM transfer tr1
where transfer_type = 'Positive' group by transfer_id)
EXCEPT
(SELECT SUM (amount) from transfer tr2
where transfer_type = 'Negative' group by transfer_id)))
How could I convert the query not to see the error :
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Many thanks in advance
You can construct a query in a way to turn additions into subtractions for 'Negative' values, like this:
SELECT
transfer_id
, SUM (
CASE 'transfer_type'
WHEN 'Positive' THEN amount
WHEN 'Negative' THEN -amount
ELSE NULL
END
) AS total
FROM transfer
GROUP BY transfer_id
Now a single SUM is used, with the sign of the addition controlled by the CASE expression.

Compare two numbers and set a value of 1 or 0 to the Highest or Lowest in Excel or SQL Server 2012

I have a list of players and a list of their scores in a game. I'd like to compare the two columns, and return a value of 1 or 0. 1 = Highest number, 0 = Lowest number. If the two values are equal, I'd like to return two 1's.
How can I do this using Excel or SQL Server 2012?
If I understood you correctly, you want the player with the highest score in a team to be marked with 1 and the lowest with 0. In that case:
SELECT t.team_id,t.player_id,t.score,
case when t.score = s.max_score then 1
when t.score = s.min_score then 0
end as pro_ind
FROM YourTable t
INNER JOIN(select team_id,max(score) as max_score,min(score) as min_score
FROM YourTable
GROUP BY team_id) s
ON (t.team_id = s.team_id)
Of course I guessed the names of the columns, so you will have to adjust it.

Resources