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
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
)
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
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.
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...
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