sql server select value depend by date - sql

I have 2 tables :
documents
(docId | date | value | currencyid | currencyRate | netvalue )
1 | 2017/07/30 | 777 | EUR | 4.55 | 150.66
2 | 2017/07/30 | 456 | EUR | 4.55 | 100.00
3 | 2017/07/29 | 440 | RON | 1.00 | 440.00
4 | 2017/07/28 | 999 | RON | 1.00 | 999.00
currencyrates
(only for currencyid = EUR)
(date | currencyRate)
2017/07/30 | 4.55
2017/07/29 | 4.53
2017/07/28 | 4.48
I need to extract by month, the total sum in euro for all documents. My problem is when I try to convert the local value (RON) from documents.value in EURO.
Example 1 in documents : when currencyid = EUR, netvalue is automaticaly calculated from value/currencyRate (in documents) and only what I need there is to extract documents.netvalue
the problem is :
Example 2 in documents : when currencyid = RON, netvalue is represented in RON and i need to convert it in EURO with the value at facturated date (not present date). So, I need to extract the currencyRate from currencyrates table for each date and use it in a CASE to divide value (in RON) at it.
and my query :
SELECT
p.name Client, year(d.date) AS Year, month(d.date) AS Month, CONVERT(DECIMAL(10,2),d.CurrencyNetValue) CurrencyNetValue, d.CurrencyId,
CASE
WHEN d.CurrencyId = 1 THEN d.CurrencyNetValue/(select top 1(c.CurrencyRate) from CurrencyRates c inner join documents d on d.date=c.date where c.CurrencyId=2)
WHEN d.CurrencyId = 2 THEN d.CurrencyNetValue
END
AS EuroNetValue
FROM documents d
inner join partners p ON d.partnerid = p.partnerid
WHERE d.doctypeid = 200
ORDER BY d.date DESC
the error is in subquery, where i try to return the value of currencyRate at the date of facture. I need to return only a number, not all column

Solved :
Needed to add an inner join for a new "table"
inner join (select * from CurrencyRates where CurrencyId = 2) as cr on d.Date = cr.Date

Related

How to select company which have two groups

I still tried select all customers which is in two group. Duplicate from customers is normal because select is from invoice but I need to know the customers who had a group in the first half year and jumped to another in the second half year.
Example:
SELECT
f.eankod as kod, --(groups)
ad.kod as firma, --(markComp)
f.nazfirmy as nazev, --(nameComp)
COUNT(ad.kod),
sum(f.sumZklZakl + f.sumZklSniz + f.sumOsv) as cena_bez_dph --(Price)
FROM
ddoklfak as f
LEFT OUTER JOIN aadresar ad ON ad.idfirmy = f.idfirmy
WHERE
f.datvyst >= '2017-01-01'
and f.datvyst <= '2017-12-31'
and f.modul like 'FAV'
GROUP BY
f.eankod,
ad.kod,
f.nazfirmy
HAVING COUNT (ad.kod) > 1
order by
ad.kod
Result:
GROUP markcomp nameComp price
| D002 | B5846 | Cosmopolis | price ... |
| D003 | B6987 | Tismotis | price ... |
| D009 | B8974 | Teramis | price ... |
| D006 | B8876 | Kesmethis | price ... | I need this, same company but diferent group, because this
| D008 | B8876 | Kesmethis | price ... | company jumped. I need know only jumped company. (last two rows from examples)
Thx for help.
You can use a CTE to find out which nameComp show up multiple times, and keep those ones only. For example:
with
x as (
-- your query
)
select * from x where nameComp in (
select nameComp from x group by nameComp having count(*) > 1
)

How to count number of clients who have not paid their's first loan repayment in time?

I have a table which looks like
ContractID | RepaymentNumber | MaturityDateID | PaymentDateID | Amount
242105 | 1 | 20170605 | 20170604 | 4825
322105 | 32 | 20170608 | 20170601 | 825
245105 | 6 | 20170611 | 20170804 | 148
578105 | 11 | 20170711 | 20170809 | 0
578185 | 21 | 20170712 | 19000101 | 3541
Where MaturityDateID is an date (in INT) to which a client should pay his loan according to his repaymentschedule and paymentDateID is a date in INT when he really send the payment. Amount = 0 means a client has a postpone in his repaymentschedule. RepaymentNumber is a count number of client's payment.
Now, I need to count a number of clients who's first repayment for a loan is PaymentDateID > MaturityDateID. The issue is the can have countless number of postpones, so for the first repayment, the column RepaymentNumber can be arbitary.
I've tried:
;WITH Nots AS (
SELECT
c.ApplicationID
--,rs.Amount
,RANK() OVER (ORDER BY rs.Amount) AS RankID
FROM
dim.Contract c
JOIN dim.Application a ON c.ApplicationID = a.ApplicationID
JOIN dim.Calendar cal ON a.ApplicationDateID = cal.DateId
JOIN dim.CreditAdvisor ca ON a.OriginalCreditAdvisorID = ca.CreditAdvisorId
JOIN dim.RepaymentSchedule rs ON c.ContractID = rs.ContractID
WHERE
((cal.CalendarYear >= 2016) AND (rs.MaturityDateID < 20170811)) -- Since given year to this date
AND ((rs.PaymentDateID = 19000101) OR (rs.PaymentDateID > rs.MaturityDateID))
GROUP BY
1
)
SELECT *
FROM Nots
WHERE RankID > 1
Any help would be appreciated. Thanks in advance.
If the issue is just that postpones, defined as those rows with Amount = 0 don't count as payments and you want the first "real" payment, you would just need to exclude those rows with Amount = 0. The WHERE statement would then be:
WHERE
((cal.CalendarYear >= 2016) AND (rs.MaturityDateID < 20170811)) -- Since given year to this date
AND ((rs.PaymentDateID = 19000101) OR (rs.PaymentDateID > rs.MaturityDateID))
AND rs.Amount > 0

how to get daily profit from sql table

I'm stucking for a solution at the problem of finding daily profits from db (ms access) table. The difference wrt other tips I found online is that I don't have in the table a field "Price" and one "Cost", but a field "Type" which distinguish if it is a revenue "S" or a cost "C"
this is the table "Record"
| Date | Price | Quantity | Type |
-----------------------------------
|01/02 | 20 | 2 | C |
|01/02 | 10 | 1 | S |
|01/02 | 3 | 10 | S |
|01/02 | 5 | 2 | C |
|03/04 | 12 | 3 | C |
|03/03 | 200 | 1 | S |
|03/03 | 120 | 2 | C |
So far I tried different solutions like:
SELECT
(SELECT SUM (RS.Price* RS.Quantity)
FROM Record RS WHERE RS.Type='S' GROUP BY RS.Data
) as totalSales,
(SELECT SUM (RC.Price*RC.Quantity)
FROM Record RC WHERE RC.Type='C' GROUP BY RC.Date
) as totalLosses,
ROUND(totalSales-totaleLosses,2) as NetTotal,
R.Date
FROM RECORD R";
in my mind it could work but obviously it doesn't
and
SELECT RC.Data, ROUND(SUM (RC.Price*RC.QuantitY),2) as DailyLoss
INTO #DailyLosses
FROM Record RC
WHERE RC.Type='C' GROUP BY RC.Date
SELECT RS.Date, ROUND(SUM (RS.Price*RS.Quantity),2) as DailyRevenue
INTO #DailyRevenues
FROM Record RS
WHERE RS.Type='S'GROUP BY RS.Date
SELECT Date, DailyRevenue - DailyLoss as DailyProfit
FROM #DailyLosses dlos, #DailyRevenues drev
WHERE dlos.Date = drev.Date";
My problem beyond the correct syntax is the approach to this kind of problem
You can use grouping and conditional summing. Try this:
SELECT data.Date, data.Income - data.Cost as Profit
FROM (
SELECT Record.Date as Date,
SUM(IIF(Record.Type = 'S', Record.Price * Record.Quantity, 0)) as Income,
SUM(IIF(Record.Type = 'C', Record.Price * Record.Quantity, 0)) as Cost,
FROM Record
GROUP BY Record.Date
) data
In this case you first create a sub-query to get separate fields for Income and Cost, and then your outer query uses subtraction to get actual profit.

how can i have my sql show the sum of 2 tables at the same time?

I've tried to show the result of sum of bill total and vat total (that customer paid VAT) and the sum of all(bill_total + vat) for monthly. However, my sql command show nothing after it executed. So could you kindly please help me as my sql knowledge was so limit.
My tables are below
tbl_bill_total
bill_id | bill_total | cust_id | showndate
1 | 1000 | 12 | 12/10/13
2 | 1200 | 13 | 1/11/13
3 | 500 | 12 | 3/11/13
tbl_vat_bill_total
vat_id | vat_total | if_paid| showndate | cust_id
1 | 400 | false | 13/10/13 | 14
2 | 500 | true | 14/11/13 | 12
3 | 100 | false | 15/11/13 | 11
4 | 200 | true | 20/11/13 | 12
The expected result should be like this
bill_total | vat_total | Sum_of_all | month
1000 | 0 | 1000 | 10
1700 | 700 | 2400 | 11
Thank you very much
** sorry I've changed the expected result… As it is a yearly report, so the outcome should list all sales in one year. *
below is my attempt that failed...
SELECT
Sum(tbl_bill_total.bill_total) AS bill_totalOfSum,
Sum(tbl_vat_bill_total.vat_total) AS vat_totalOfSum,
tbl_vat_bill_total.if_paid,
Month([tbl_bill_total.showndate]) AS month1
FROM
tbl_bill_total
INNER JOIN
tbl_vat_bill_total
ON tbl_bill_total.cust_id = tbl_vat_bill_total.cust_id
GROUP BY
tbl_vat_bill_total.if_paid,
Month([tbl_bill_total.showndate])
HAVING (((tbl_vat_bill_total.if_paid)=True));
Ok, I haven't used Access in awhile, but I think the following should work:
select
sum(tbt.bill_total) as bill_total_
,iif(sum_vat_total is null, 0, sum_vat_total) as vat_total_
,iif(sum_vat_total is null, 0, sum_vat_total) + sum(bill_total) as sum_of_all
,month(showndate) as month
from tbl_bill_total tbt
left join (
select
sum(vat_total) as sum_vat_total
,month(showndate) as month
from tbl_vat_bill_total
where if_paid = true
and year(showndate) = 2013
group by
month(showndate)
) tvt
on tvt.month = month(tbt.showndate)
where year(showndate) = 2013
group by
month(showndate)
,sum_vat_total
Of course, this assumes that you will at least have one record per month in tbl_bill_total since that is the source of our month field.
If you have months where there are tbl_vat_bill_total records but no tbl_bill_total records (or no records in either table), you will need a more complex solution - likely with a date table.
Create a query like this call it say q_bill_sum
Select Sum(bill_total) as total, 'Bill' as Total_Type, Month(showndate) as bill_Month
From tbl_bill_total
Where Year(showndate) = 2013
group by Total_Type, Bill_month
Union
Select Sum(vat_total), 'Vat' as Total_Type, Month(showndate) as bill_month
From tbl_vat_bill_total
Where Year(showndate) = 2013 and if_paid = true
group by Total_Type, Bill_month
You end up with
1000 Bill 10
1700 Bill 11
0 Vat 10
700 Vat 11
then
Select b.Total, ifnull(v.total,0), b.bill_Month
From q_bill_sum b
left join q_bill_sum v On v.Bill_month = b.Bill_month
should be close, but you never did answer my question about having vat in a month with no bill in a month.
I think anyway, access isn't my strong suit, but when I have to do a query that does a lot, I always break it down into bits, then when it works I try to streamline if it seems horrible...

Calculations over Multiple Rows SQL Server

If I have data in the format;
Account | Period | Values
Revenue | 2013-01-01 | 5432
Revenue | 2013-02-01 | 6471
Revenue | 2013-03-01 | 7231
Costs | 2013-01-01 | 4321
Costs | 2013-02-01 | 5672
Costs | 2013-03-01 | 4562
And I want to get results out like;
Account | Period | Values
Margin | 2013-01-01 | 1111
Margin | 2013-02-01 | 799
Margin | 2013-03-01 | 2669
M% | 2013-01-01 | .20
M% | 2013-02-01 | .13
M% | 2013-03-01 | .37
Where Margin = Revenue - Costs and M% is (Revenue - Costs)/Revenue for each period.
I can see various ways of achieving this but all are quite ugly and I wanted to know if there was elegant general approach for these sorts of multi-row calculations.
Thanks
Edit
Some of these calculations can get really complicated like
Free Cash Flow = Margin - Opex - Capex + Change in Working Capital + Interest Paid
So I am hoping for a general method that doesn't require lots of joins back to itself.
Thanks
Ok, then just Max over a Case statement, like such:
with RevAndCost as (revenue,costs,period)
as
(
select "Revenue" = Max(Case when account="Revenue" then Values else null end),
"Costs" = MAX(Case when account="Costs" then values else null end),
period
from data
group by period
)
select Margin = revenue-costs,
"M%" = (revenue-costs)/nullif(revenue,0)
from RevAndCost
Use a full self-join with a Union
Select 'Margin' Account,
coalesce(r.period, c.period) Period,
r.Values - c.Values Values
From myTable r
Full Join Mytable c
On c.period = r.period
Union
Select 'M%' Account,
coalesce(r.period, c.period) Period,
(r.Values - c.Values) / r.Values Values
From myTable r
Full Join Mytable c
On c.period = r.period
Here I use a Common Table Expression to do a full outer join between two instances of your data table to pull in Revenue and Costs into 1 table, then select from that CTE.
with RevAndCost as (revenue,costs,period)
as
(
select ISNULL(rev.Values,0) as revenue,
ISNULL(cost.values,0) as costs,
ISNULL(rev.period,cost.period)
from data rev full outer join data cost
on rev.period=cost.period
)
select Margin = revenue-costs,
"M%" = (revenue-costs)/nullif(revenue,0)
from RevAndCost
I'd do it like this:
SELECT r.PERIOD, r.VALUES AS revenue, c.VALUES AS cost,
r.VALUES - c.VALUES AS margin, (r.VALUES - c.VALUES) / r.VALUES AS mPct
FROM
(SELECT PERIOD, VALUES FROM t WHERE
ACCOUNT = 'revenue') r INNER JOIN
(SELECT PERIOD, VALUES FROM t WHERE
ACCOUNT = 'costs') c ON
r.PERIOD = c.PERIOD