SQLite3 creating a view profit combining rows twice based on column - sqlite

Given a table
symbol|action|quantity|price
foo|buy|1|-10.00
foo|sell|1|10.50
bar|buy|1|-50.00
bar|sell|1|50.50
I am trying to create a view that shows profit per symbol
I've tried several variations of below with multiple 'order by' but not getting the expected output
create view if not exists profit_view as select symbol,sum(price * quanity) as profit from trans group by symbol;
What I'd like is a view that shows or something close to that
symbol|profit|percent
foo|.50|5

Assuming each symbol only has a single buy and sell record we can try:
SELECT
symbol,
SUM(quantity*price) AS profit,
100.0 * SUM(quantity*price) /
ABS(MAX(CASE WHEN action = 'buy' THEN quantity*price END)) AS percent
FROM trans
GROUP BY
symbol;

Related

How can I calculate a field based on fields in other tables while inserting a record (in a procedure)

I'm sorry for the confusing title, but couldn't find another way to ask it.
Let's say I want to write a procedure add_salesline. I enter all the fields with parameters, except subtotal. Subtotal (just the price for the salesline) needs to be calculated based on fields in other tables such as productprice in the table products, pricereduction in the table promotion, etc. (based on the properties).
How can I do this? I've been trying to solve this problem for a good week now, and it's just not working...
Presumably one of the parameters passed to procedure add_salesline() is productid, or whatever. So you use that to SELECT products.productprice, promotion.pricereduction and whatever else you need to perform the calculation.
The purpose of writing a stored procedure is to associate several calls into a single program unit. So add_salesline() might look something like this (lots of caveats because your question is very light on details):
create or replace procedure add_salesline(
p_orderno in salesline.orderno%type
, p_salesqty in salesline.salesqty%type
, p_productid in products.productid%type
)
is
new_rec salesline%rowtype;
begin
new_rec.orderno := p_orderno;
new_rec.salesqty := p_salesqty;
new_rec.productid := p_productid;
select p_salesqty * (p.productprice * nvl(pp.pricereduction, 1))
into new_rec.subtotal
from products p
left outer join promotion pp
on pp.productid = p.productid
where p.productid = p_productid
;
insert into salesline
value new_rec;
end;
This code assumes pricereduction is a rate. If the value is an absolute discount the formula will be different (p.productprice - nvl(pp.pricereduction, 0)). Or if it's a replacement price: coalesce(pp.pricereduction, p.productprice).

MS Acess: max(Date/Time field) on query when field may contain 00:00:00

I am trying to build a Query in MS Access that returns the last date/time for a given entity ID. Research shows that using the MAX() function on the corresponding field and using GROUP BY on the remaining fields appears to be the way to go.
However, this doesn't seem to work in the presence of values that hold 0 hours, 0 minutes and 0 seconds, as it shows those values as well. The query's SQL is as follows:
SELECT Int(Historico_Classificacoes.ID_Entidade) AS ID_Entidade, Max(Historico_Classificacoes.Timestamp_Classificacao) AS [Data da última classificação], Historico_Classificacoes.US_Indicia_Pais_Constituicao, Historico_Classificacoes.US_Indicia_Responsabilidades_Fiscais, Historico_Classificacoes.US_Indicia_Morada_Coletiva, Historico_Classificacoes.US_Indicia_Telefone, Historico_Classificacoes.US_Indicia_Proveniencia_Capital, Historico_Classificacoes.US_Indicia_Beneficiários, Historico_Classificacoes.US_Indicia_Naturalidade, Historico_Classificacoes.US_Indicia_Nacionalidade, Historico_Classificacoes.US_Indicia_Morada_Singular, Historico_Classificacoes.US_Indicia_Laboral
FROM Historico_Classificacoes
GROUP BY Int(Historico_Classificacoes.ID_Entidade), Historico_Classificacoes.US_Indicia_Pais_Constituicao, Historico_Classificacoes.US_Indicia_Responsabilidades_Fiscais, Historico_Classificacoes.US_Indicia_Morada_Coletiva, Historico_Classificacoes.US_Indicia_Telefone, Historico_Classificacoes.US_Indicia_Proveniencia_Capital, Historico_Classificacoes.US_Indicia_Beneficiários, Historico_Classificacoes.US_Indicia_Naturalidade, Historico_Classificacoes.US_Indicia_Nacionalidade, Historico_Classificacoes.US_Indicia_Morada_Singular, Historico_Classificacoes.US_Indicia_Laboral
ORDER BY Int(Historico_Classificacoes.ID_Entidade);
The Historico_Classificacoes table currently holds the following data:
"ID_Entidade";"Timestamp_Classificacao";"Classificacao_DMIF";"Notacao_Risco_BCFT";"US_Indicia_Pais_Constituicao";"US_Indicia_Responsabilidades_Fiscais";"US_Indicia_Morada_Coletiva";"US_Indicia_Telefone";"US_Indicia_Proveniencia_Capital";"US_Indicia_Beneficiários";"US_Indicia_Naturalidade";"US_Indicia_Nacionalidade";"US_Indicia_Morada_Singular";"US_Indicia_Laboral"
"62";20/9/2015 00:00:00;1;30;1;1;1;1;1;1;1;1;1;0
"62";28/9/2015 10:43:38;1;30;1;1;1;1;1;1;1;1;1;1
"62";29/9/2015 17:52:24;1;30;1;1;1;1;1;1;1;1;1;1
"62";29/9/2015 17:52:40;1;30;1;1;1;1;1;1;1;1;1;1
"98";20/9/2015 00:00:00;2;15;1;1;1;1;1;1;0;0;0;0
"98";20/9/2015 00:00:01;0;0;0;0;0;0;0;0;0;0;0;0
The query, when executed in Datasheet View, outputs the following:
"ID_Entidade";"Data da última classificação";"US_Indicia_Pais_Constituicao";"US_Indicia_Responsabilidades_Fiscais";"US_Indicia_Morada_Coletiva";"US_Indicia_Telefone";"US_Indicia_Proveniencia_Capital";"US_Indicia_Beneficiários";"US_Indicia_Naturalidade";"US_Indicia_Nacionalidade";"US_Indicia_Morada_Singular";"US_Indicia_Laboral"
62;29/9/2015 17:52:40;1;1;1;1;1;1;1;1;1;1
62;20/9/2015 00:00:00;1;1;1;1;1;1;1;1;1;0
98;20/9/2015 00:00:00;1;1;1;1;1;1;0;0;0;0
98;20/9/2015 00:00:01;0;0;0;0;0;0;0;0;0;0
There are duplicated records for entities 62 and 98, when only one record for each was expected. Am I missing something here? Why are the entries whose values hold 00:00:00 present?
You may want to consider using an additional query as an intermediate step that identifies the MAX Date/Time combination for each group ID first, then a follow up query that pulls the entire record where that Group ID, Date and Time match, this will ensure you won't have to use First or Min on the rest of your fields, and you will always get the correct data
You use Group By for the last fields like US_Indicia_Morada_Singular and US_Indicia_Laboral. You'll have to use First, Last, Min, or Max on these as well.
Here is your attempt (without the repeated alias)
SELECT INT(ID_Entidade) AS ID_Entidade
, MAX(Timestamp_Classificacao) AS [Data da última classificação]
, US_Indicia_Pais_Constituicao
, US_Indicia_Responsabilidades_Fiscais
, US_Indicia_Morada_Coletiva
, US_Indicia_Telefone
, US_Indicia_Proveniencia_Capital
, US_Indicia_Beneficiários
, US_Indicia_Naturalidade
, US_Indicia_Nacionalidade
, US_Indicia_Morada_Singular
, US_Indicia_Laboral
FROM Historico_Classificacoes
GROUP BY INT(ID_Entidade)
, US_Indicia_Pais_Constituicao
, US_Indicia_Responsabilidades_Fiscais
, US_Indicia_Morada_Coletiva
, US_Indicia_Telefone
, US_Indicia_Proveniencia_Capital
, US_Indicia_Beneficiários
, US_Indicia_Naturalidade
, US_Indicia_Nacionalidade
, US_Indicia_Morada_Singular
, US_Indicia_Laboral
ORDER BY INT(ID_Entidade);
From you comments, here is SQL that is close to what you need. I have added the field "AnotherField" for you as you may or may not need to add field here.
This currently selects the whole record from the table, but only the single "most recent" record for each value found in the AnotherField is listed.
It may be that you need more that one field where AnotherField appears in the SQL. Think of the field you use instead of AnotherField as being the fields that need to be used to find the maximum date record.
SELECT Main.*
FROM Historico_Classificacoes AS Main
INNER JOIN ( SELECT AnotherField
, MAX(Timestamp_Classificacao) AS [MaxDate]
FROM Historico_Classificacoes
GROUP BY AnotherField
)
AS MostRecent
ON ( Main.AnotherField = MostRecent.AnotherField
AND
Main.Timestamp_Classificacao = MostRecent.MaxDate
)

How to Show Two table columns in a aspxgridview?

I have tow tables in mssql server, Car & Weight.
Car has IDCar, Name, Username, Description columns.
And Weight has IDWeight, CarID, Name, Date, Weight columns.
I want to show Name of Car table in the first column of aspx gridview and show weight and date from Weight Table.
The Name is static, but everyday user must input date and weight for each car.
I wish it was clear about it!
Write a query with the join with both tables and get the desired result and then bind that result to the gridview. Your query can be like,
Select c.Name,w.Weight,w.Date
FROM
Car c LEFT Join Weight w
ON c.CarID = w.CarID
UPDATE
Applied left join after the comment.Left Join will give you all the car names from the Car table irrespective of if there are data present in the Weight table for that car or not.
To use the Where in join just use it as normal where clause.
WHERE
w.Date = GETDATE() //Change according your need
AND w.Weight = 110 //Change according your need
To read more about join
To bind datatable to the Gridview read here
select car.Name,weigth.weight,weigth.date from car
inner join weight on car.carid=weigth.carid
you can add a filter to specifiy which item you want using where clause:
where carid in ('xx','123','guid') and weight.weight between 100 and 200

SQLITE getting trigger to check against table1 and insert into table2

I have a reservation table which the user will insert records into.
The User does not select the car just the type.
Once the record is inserted I want some triggers to do the following:-
The date and vehicle combination to a log file the data and vehicle are UNIQUE(date,car) so the same reservation cannot be made twice therefore a car cannot be double booked.
SO my issue is how do I now get the trigger to select the next available car of that type?
I can get it to select the next car by just saying Car.carid != Log.carid but that is not using the date as a second check so I could not then use the vehicle on another date.
Simply putting AND between the check doesnt work meaning
WHERE Car.carid != Log.carid AND Reservation.date != C.datewhen
Some guidance would be much appreciated!
I think this query is what you are after...
SELECT MIN(c.carid)
FROM all_cars c
WHERE c.type = 'CAR TYPE'
AND NOT EXISTS
(SELECT 1
FROM reservation r
WHERE r.date = 'THE DATE'
AND r.carid = c.carid)
If the query returns a NULL value then no cars are available.
Or you could take off the MIN and just use the first record returned.

Display grand total as the sum of averages (custom subtotal)

I have SQL Server query, which returns the following data:
I want to display the data in RDLC 2008 Report using matrix format which should give the following result:
The Grand Total of Qty field should return 12 for January & 14 for February.
I have tried many different methods one of which is by using the following expression in the matrix 'Qty' textbox :
=IIF(InScope("RowGroup_Category")
,IIF(InScope("RowGroup_SubCategory")
,Fields!Qty.Value
,Code.GetAverageMemberCount(Cint(Avg(Fields!Qty.Value)))
)
,Code.TotalMemberCount
)
The above functions are written in Report Properties Code as below:
Public Dim TotalMemberCount As Integer = 0
Function GetAverageMemberCount(ByVal AverageMemberCount As Integer) As Integer
TotalMemberCount = TotalMemberCount + AverageMemberCount
Return AverageMemberCount
End Function
I have also tried RunningValue(Fields!Qty.Value,Sum,"RowGroup_Category") and many such functions but I am unable to get the exact results. any help would be appreciated.. Thank you
Try adding this into a new column as a test:
RunningValue(Avg(Fields!MemberCount.Value,"RowGroup_Category"),SUM,Nothing)
If the value is correct you should be able to change SUM into MAX when setting this expression in the grand total field.
You can refer to the total like code.TotalMemberCount instead of using a get function
but i don't think you need this function in this case.
Check the following blog for a simular variable referencing situation
The only solution I could find that worked for me to solve this is to calculate the averages in a different dataset and use lookup functions to fill the grand total from there.
In your case I would add a key column in your original dataset:
select Category + '|' + Month as key, Category, SubCategory, Month, Qty, Amt
from YourTable
Create another dataset using:
select Category + '|' + Month as key, Category, Month, avg(Qty)
from YourTable
group by Category, Month
Add the second result as DataSet2 to the report. (In Visual Studio in the Report Data pane right click on DataSets.)
Add to the Report Properties -> Code section the following:
Function SumArray(varArray as array) as Decimal
Dim retVal As Decimal = 0
For Each item As Decimal In varArray
retVal = retVal + item
Next
Return retVal
End Function
Finally in the report use the following expression for Grand Total under Qty:
=code.SumArray(Lookupset(Fields!key.Value, Fields!key.Value, Fields!qty.Value, "DataSet2"))
P.S.: Make sure that the second dataset is also filled by your code the same way the original was.

Resources