how to shorten or optimize JOIN query in postgres - postgresql

I got following query, in which I am joining 4 times. But it takes lot of time to return the result.
Is there any way to optimize this query ?
SELECT T1.wbd_date as WBD_DATE, to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp,
T4.wbd_value as SWT, T5.wbd_value as Expval
FROM (
SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value
FROM wb_block_data ) T1
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112 and to_char(T2.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116 and to_char(T3.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120 and to_char(T4.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661 and to_char(T5.wbd_date,'MM YYYY')='07 2019'

You are essentially doing a pivot, doing that using conditional aggregation might be faster:
select wbd_attribute_id, block_no, wbd_date,
max(wbd_value) filter (where wbd_attribute_id = 152112) as AmbHum,
max(wbd_value) filter (where wbd_attribute_id = 152116) as AmbTemp,
max(wbd_value) filter (where wbd_attribute_id = 152120) as swt,
max(wbd_value) filter (where wbd_attribute_id = 152120) as Expval
from (
SELECT wbd_attribute_id, wbd_date, to_char(wbd_block_no, 'fm00') as block_no, wbd_value
FROM wb_block_data
where wbd_attribute_id in (152112, 152116, 152120, 150661)
and wbd_date >= DATE '2019-07-01'
and wbd_date < DATE '2019-08-01'
) t
group by wbd_attribute_id, wbd_date, block_no
You want an index on (wbd_attribute_id, wbd_date) for that.

An index such as the following might work:
CREATE INDEX idx ON wb_block_data (wbd_date, wbd_block_no, wbd_attribute_id);
However, we would also need to make the join conditions sargable:
SELECT T1.wbd_date as WBD_DATE, to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp, T4.wbd_value as SWT, T5.wbd_value as Expval
FROM
(
SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value
FROM wb_block_data
) T1
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112 and T2.wbd_date >= '2019-07-01' and T2.wbd_date < '2019-08-01'
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116 and T3.wbd_date >= '2019-07-01' and T3.wbd_date < '2019-08-01'
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120 and T4.wbd_date >= '2019-07-01' and T4.wbd_date < '2019-08-01'
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661 and T5.wbd_date >= '2019-07-01' and T5.wbd_date < '2019-08-01';
The only change I made to your query was to express the date requirement as a range, without using to_char:
wbd_date >= '2019-07-01' and wbd_date < '2019-08-01'
This is sargable, meaning that Postgres might able to use an index on the wbd_date column to satisfy the July, 2019 date range.

I changed query to this and with this I am getting desired result quickly
SELECT T1.wbd_date as WBD_DATE, to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp,
T4.wbd_value as SWT, T5.wbd_value as Expval
FROM (
SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value
FROM wb_block_data where to_char(wbd_date,'MM YYYY')='07 2019') T1
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661

Related

N1QL query dropping records after join with a subquery

The Below Query is dropping records when i join 2 N1QL sub queries -
We are using couchbase and using N1QL queries.
Full Query -
select
t3.appName,
t3.uuid_proj as uuid,
t3.description,
t3.env,
t3.productStatus
from
( select
t1.uuid as uuid_proj ,
t1.appName as appName ,
t1.description as description,
t2.env as env,
t2.productStatus as productStatus
from
(
select
api_external.uuid ,
api_external.data.appName ,
api_external.data.description
from `api_external`
where type = 'partnerApp'
and data.companyId = '70a149da27cc425da86cba890bf5b143' )t1
join
(
select
api_external.data.env,
api_external.data.productStatus,
api_external.data.partnerAppId
from
`api_external`
where type = 'integration' )t2
on t1.uuid = t2.partnerAppId
) as t3
join (
select t4.uuid as uuid_agg , min(t5.env) as env
from
(select api_external.uuid from `api_external` where type = 'partnerApp' and data.companyId = '70a149da27cc425da86cba890bf5b143' )as t4 join
(select api_external.data.env, api_external.data.partnerAppId from `api_external` where type = 'integration' ) as t5
on t4.uuid = t5.partnerAppId
group by t4.uuid
) as t6
on
t3.uuid_proj = t6.uuid_agg and t3.env = t6.env
As you see it has 2 sub queries -
The below subquery gives 16 records -
select
t1.uuid as uuid_proj
from
(
select
api_external.uuid ,
api_external.data.appName ,
api_external.data.description
from `api_external`
where type = 'partnerApp'
and data.companyId = '70a149da27cc425da86cba890bf5b143' )t1
join
(
select
api_external.data.env,
api_external.data.productStatus,
api_external.data.partnerAppId
from
`api_external`
where type = 'integration' )t2
on t1.uuid = t2.partnerAppId
group by t1.uuid
Also the other subquery also gives 16 records -
select t4.uuid as uuid_agg , min(t5.env) as env
from
(select api_external.uuid from `api_external` where type = 'partnerApp' and data.companyId = '70a149da27cc425da86cba890bf5b143' )as t4 join
(select api_external.data.env, api_external.data.partnerAppId from `api_external` where type = 'integration' ) as t5
on t4.uuid = t5.partnerAppId
group by t4.uuid
By Logic join of both the queries on the same grain UUID must also give 16 records . But it gives only 1 .
What am i doing wrong Please help
The query uses many subqueries and hit the issue.
Try following simplified version
CREATE INDEX ix1 ON api_external(data.companyId, uuid, data.appName, data.description) WHERE type = "partnerApp";
CREATE INDEX ix2 ON api_external(data.partnerAppId, data.env, data.productStatus) WHERE type = "integration";
WITH ct3 AS (SELECT t1.uuid, t1.data.appName, t1.data.description,
t2.data.env, t2.data.productStatus
FROM api_external AS t1
JOIN api_external AS t2 ON t1.uuid = t2.data.partnerAppId
WHERE t1.type = "partnerApp"
AND t1.data.companyId = "70a149da27cc425da86cba890bf5b143"
AND t2.type = "integration"
AND t2.data.partnerAppId IS NOT NULL),
ct6 AS ( SELECT t4.uuid AS uuid_agg , MIN(t5.data.env) AS env
FROM api_external AS t4
JOIN api_external AS t5 ON t4.uuid = t5.data.partnerAppId
WHERE t4.type = "partnerApp"
AND t4.data.companyId = "70a149da27cc425da86cba890bf5b143"
AND t5.type = "integration"
AND t5.data.partnerAppId IS NOT NULL
GROUP BY t4.uuid)
SELECT t3.*
FROM ct3 AS t3
JOIN ct6 AS t6 ON t3.uuid = t6.uuid_agg and t3.env = t6.env;
If same results see following works . After JOIN get all the fields of results of MIN env record each group
SELECT m[1].*
FROM api_external AS t4
JOIN api_external AS t5 ON t4.uuid = t5.data.partnerAppId
WHERE t4.type = "partnerApp"
AND t4.data.companyId = '70a149da27cc425da86cba890bf5b143'
AND t5.type = "integration"
AND t5.data.partnerAppId IS NOT NULL
GROUP BY t4.uuid
LETTING m = MIN([t5.data.env, {t4.uuid, t4.data.appName, t4.data.description,
t5.data.env, t5.data.productStatus}]);

How to PIVOT this query and display only TOP 10 records filtered by SUM(NetWrittenPremium) DESC

In this query I cant understand what would be the proper syntax to PIVOT it by month and also display just top 10 records based on SUM(NetWrittenPremium).
;with cte_TopClasses
AS (
select
b.YearNum,
b.MonthNum,
REPLACE(ClassCode,'+','') + ' - '+ QLL.Description as Description,
SUM( Premium) as NetWrittenPremium
FROM tblCalendar b
LEFT JOIN ProductionReportMetrics prm ON b.MonthNum=Month(prm.EffectiveDate) AND b.YearNum = YEAR(EffectiveDate)
AND prm.EffectiveDate >=DateAdd(yy, -1, DATEADD(d, 1, EOMONTH(GETDATE()))) AND prm.EffectiveDate <= EOMONTH(GETDATE()) AND CompanyLine = 'Ironshore Insurance Company'
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN (SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID as LocID, MAX(ClassCode) as ClCode
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocID = nqI.LocationID AND nqA.ClCode = nqI.ClassCode ) QLL
ON QLL.LocationID = QL.LocationID
WHERE ( b.YearNum = YEAR(GETDATE())-1 and b.MonthNum >= MONTH(GETDATE())+1 ) OR
( b.YearNum = YEAR(GETDATE()) and b.MonthNum <= MONTH(GETDATE()) )
GROUP BY b.YearNum,b.MonthNum,ClassCode, QLL.Description
)
SELECT
--TOP 10
RANK() OVER (ORDER BY NetWrittenPremium DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IS NOT NULL
ORDER BY NetWrittenPremium DESC,YearNum,MonthNum
The result should look something like that:
If I use the query below and then using matrics in SSRS to PIVOT it - then after grouping by Description it only displays me 2 Description.
;with cte_TopClasses
AS (
select
b.YearNum,
b.MonthNum,
REPLACE(ClassCode,'+','') + ' - '+ QLL.Description as Description,
SUM( Premium) as NetWrittenPremium
FROM tblCalendar b
LEFT JOIN ProductionReportMetrics prm ON b.MonthNum=Month(prm.EffectiveDate) AND b.YearNum = YEAR(EffectiveDate)
AND prm.EffectiveDate >=DateAdd(yy, -1, DATEADD(d, 1, EOMONTH(GETDATE()))) AND prm.EffectiveDate <= EOMONTH(GETDATE()) AND CompanyLine = 'Ironshore Insurance Company'
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN (SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID as LocID, MAX(ClassCode) as ClCode
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocID = nqI.LocationID AND nqA.ClCode = nqI.ClassCode ) QLL
ON QLL.LocationID = QL.LocationID
WHERE ( b.YearNum = YEAR(GETDATE())-1 and b.MonthNum >= MONTH(GETDATE())+1 ) OR
( b.YearNum = YEAR(GETDATE()) and b.MonthNum <= MONTH(GETDATE()) )
GROUP BY b.YearNum,b.MonthNum,ClassCode, QLL.Description
)
SELECT *
FROM (SELECT RANK() OVER (ORDER BY NetWrittenPremium DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IS NOT NULL) AA
WHERE AA.Rank <= 10
ORDER BY AA.NetWrittenPremium DESC, AA.YearNum, AA.MonthNum
And the result of it in SSRS matrics :
You could try something like this at the end of the query, rather than what is there now:
SELECT *
FROM (SELECT RANK() OVER (ORDER BY [Description] DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IN (SELECT [Description]
FROM (SELECT RANK() OVER (ORDER BY SUM(NetWrittenPremium) DESC) AS [Rank], [Description], SUM(NetWrittenPremium) AS total
FROM cte_TopClasses
WHERE [Description] IS NOT NULL
GROUP BY [Description]) BB
WHERE [Rank] <= 10)) AA
ORDER BY YearNum, MonthNum
This wraps the query in a SELECT, and filters the ranked results to the 10 you want.
Then use a matrix in the report to pivot the results.

Faster left join with last non-empty

Table1:
Shop
Manager
Date
Table2:
Shop
Date
Sales
I need to get Table2 with Manager field from Table1. I did the following trick:
select
t1.[Shop]
,t1.[Date]
,t1.[Sum]
,t2.[Manager]
from t1
left join t2
on t1.[Shop] = t2.[Shop]
and t2.[Date] = (select max(t2.[Date]) from t2
where t2.[Shop] = t1.[Shop]
and t2.[Date] < t1.[Date])
It works, but subquerying is very slow, so I wonder if there is more elegant and fast way to do so?
Some sample data to play around: http://pastebin.com/uLN6x5JE
may seem like a round about way but join on a single condition is typically faster
select t12.[Shop], t12.[Date], t12.[Sum]
, t12.[Manager]
from
( select t1.[Shop], t1.[Date], t1.[Sum]
, t2.[Manager]
, row_number() over (partition by t2.[Shop] order by t2.[Date] desc) as rn
from t1
join t2
on t2.[Shop] = t1.[Shop]
and t1.[Date] < t1.[Date]
) as t12
where t12.rn = 1
union
select t1.[Shop], t1.[Date], t1.[Sum]
, null as [Manager]
from t1
left join t2
on t2.[Shop] = t1.[Shop]
and t1.[Date] < t1.[Date]
group by t1.[Shop], t1.[Date], t1.[Sum]
having count(*) = 1
You may get much better performance by adding a covering index on t2 if you don't already have one:
create index T2ShopDate on t2 ([Shop], [Date]) include ([Manager])
Here is a version that uses a CTE to find all maximum manager dates first and then join back to t2 to get the manager:
;with MaxDates ([Shop], [Date], [Sum], [MaxMgrDate]) as
(
select
t1.[Shop]
,t1.[Date]
,t1.[Sum]
,max(t2.[Date])
from t1
left join t2
on t2.[Shop] = t1.[Shop]
and t2.[Date] < t1.[Date]
group by
t1.[Shop]
,t1.[Date]
,t1.[Sum]
)
select
MaxDates.[Shop]
,MaxDates.[Date]
,MaxDates.[Sum]
,t2.[Manager]
from MaxDates
inner join t2
on t2.[Date] = MaxDates.[MaxMgrDate]
You might be able to remove the second join back to t2 by using row_number():
;with MaxDates ([Shop], [Date], [Sum], [Manager], [RowNum]) as
(
select
t1.[Shop]
,t1.[Date]
,t1.[Sum]
,t2.[Manager]
,row_number() over (partition by (t1.[Shop]) order by t2.[Date] desc)
from t1
left join t2
on t2.[Shop] = t1.[Shop]
and t2.[Date] < t1.[Date]
)
select *
from MaxDates
where RowNum = 1

How do I get the max from a partitioned query using Rank ()

I want the result to return the max Rank when partitioned using the rank function.
I am using the following query.
SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time ASC
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
I figured it out! I was trying to get the max result of a rank, but if I flip order of rank from asc to desc and use a CTE I can select the the results that always have 1 as the rank as opposed to trying to get the Max. I would still like to know how to get the Max rank but this solution suits my needs.
;with cte as
(SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time desc
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
)
Select * from cte
where CorrectTrans = 1
Add select and group by and use your existing query as a sub query.
Try ..
select max([CorrectTrans]), Vendor_Id, Item_qty, Lot, Pallet_id
from (
-- Your existing query --
SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time ASC
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
-- =======================================
) x
group by Vendor_id, Item_qty, Lot, Pallet_id

set value from select for few select

I have select, iside select have 2 column. This column must be filled from same select, but I don't want use select twice for it. Is it possoble use select 1 time and after that set second column value from first?
Example:
insert into #temptable from
select
a = (select aa from table1 where quantity > 5)
b = (select aa from table1 where quantity > 5)
I need:
insert into #temptable from
select
a = (select aa from table1 where quantity > 5)
b = {value from a}
Update. I wrote bad example, I need set to BalancePrediction1 and BalancePrediction2 value from Balance
INSERT #tmpBalances
SELECT PA.ContractId AS 'ContractId',
Con.Name AS 'ContractName',
Bal.PortfolioAccountId AS 'PortfolioAccountId',
PA.Name AS 'PortfolioAccountName',
RA.GeneralId AS 'RegisterAccountGeneralId',
Bal.BalanceTypeId AS 'BalanceTypeId',
Bt.Name AS 'BalanceTypeName',
Bt.Type AS 'BalanceTypeType',
Bal.BalanceTimeType AS 'BalanceTimeType',
Bal.InstrumentId AS 'InstrumentId',
Ins.Name AS 'InstrumentName',
Ins.GeneralId AS 'InstrumentGeneralId',
(Bal.Balance -
(
SELECT COALESCE(SUM(Mov.Amount), 0)
FROM trd.Movements AS Mov
WHERE
Bal.InstrumentId = Mov.InstrumentId AND
Bal.PortfolioAccountId = Mov.PortfolioAccountId AND
Bal.BalanceTypeId = Mov.BalanceTypeId AND
Bal.BalanceTimeType = Mov.BalanceTimeType AND
DateDiff(DAY, #Date, Mov.Date) > 0 AND
-- Currency může být null a NULL = NULL nejde
COALESCE(Bal.CurrencyId, -1) = COALESCE(Mov.CurrencyId, -1)
)
) as Balance,
Balance AS 'BalancePrediction1',
Balance AS 'BalancePrediction2',
Bal.CurrencyId AS 'CurrencyId',
Ccy.Code AS 'CurrencyCode',
PA.PositionServiceType 'PositionServiceType',
Ccy.Name 'CurrencyName',
S.Nominal AS 'Nominal',
S.NominalCurrencyId AS 'NominalCurrencyId',
trd.GetCurrencyCode(S.NominalCurrencyId) AS 'NominalCurrencyCode'
FROM trd.Balances AS Bal
JOIN trd.PortfolioAccounts AS PA ON PA.Id = Bal.PortfolioAccountId
JOIN trd.Contracts AS Con ON Con.Id = PA.ContractId
JOIN trd.RegisterAccounts AS RA ON RA.Id = PA.RegisterAccountId
JOIN trd.BalanceTypes AS Bt ON Bt.Id = Bal.BalanceTypeId
JOIN trd.Instruments AS Ins ON Ins.Id = Bal.InstrumentId
LEFT OUTER JOIN trd.Currencies AS Ccy ON Ccy.Id = Bal.CurrencyId
LEFT JOIN trd.SecuritiesView S ON s.Id = Ins.Id AND DateDiff(d, S.ValidFrom, #Date) >= 0 AND (S.ValidTo IS NULL OR DateDiff(d, S.ValidTo, #Date) < 0)
AND S.InstrumentInstrumentTypePriceUnit = 1
You could do an update to the table variable after the insert.
update #tmpBalances
set BalancePrediction1 = Balance,
BalancePrediction2 = Balance
Or you can use cross apply to calculate the sum.
INSERT #tmpBalances
SELECT PA.ContractId AS 'ContractId',
Con.Name AS 'ContractName',
Bal.PortfolioAccountId AS 'PortfolioAccountId',
PA.Name AS 'PortfolioAccountName',
RA.GeneralId AS 'RegisterAccountGeneralId',
Bal.BalanceTypeId AS 'BalanceTypeId',
Bt.Name AS 'BalanceTypeName',
Bt.Type AS 'BalanceTypeType',
Bal.BalanceTimeType AS 'BalanceTimeType',
Bal.InstrumentId AS 'InstrumentId',
Ins.Name AS 'InstrumentName',
Ins.GeneralId AS 'InstrumentGeneralId',
(Bal.Balance - Mov.SumAmount) AS Balance,
(Bal.Balance - Mov.SumAmount) AS 'BalancePrediction1',
(Bal.Balance - Mov.SumAmount) AS 'BalancePrediction2',
Bal.CurrencyId AS 'CurrencyId',
Ccy.Code AS 'CurrencyCode',
PA.PositionServiceType 'PositionServiceType',
Ccy.Name 'CurrencyName',
S.Nominal AS 'Nominal',
S.NominalCurrencyId AS 'NominalCurrencyId',
trd.GetCurrencyCode(S.NominalCurrencyId) AS 'NominalCurrencyCode'
FROM trd.Balances AS Bal
JOIN trd.PortfolioAccounts AS PA ON PA.Id = Bal.PortfolioAccountId
JOIN trd.Contracts AS Con ON Con.Id = PA.ContractId
JOIN trd.RegisterAccounts AS RA ON RA.Id = PA.RegisterAccountId
JOIN trd.BalanceTypes AS Bt ON Bt.Id = Bal.BalanceTypeId
JOIN trd.Instruments AS Ins ON Ins.Id = Bal.InstrumentId
LEFT OUTER JOIN trd.Currencies AS Ccy ON Ccy.Id = Bal.CurrencyId
LEFT JOIN trd.SecuritiesView S ON s.Id = Ins.Id AND DateDiff(d, S.ValidFrom, #Date) >= 0 AND (S.ValidTo IS NULL OR DateDiff(d, S.ValidTo, #Date) < 0)
AND S.InstrumentInstrumentTypePriceUnit = 1
CROSS APPLY (SELECT COALESCE(SUM(Mov.Amount), 0)
FROM trd.Movements AS Mov
WHERE
Bal.InstrumentId = Mov.InstrumentId AND
Bal.PortfolioAccountId = Mov.PortfolioAccountId AND
Bal.BalanceTypeId = Mov.BalanceTypeId AND
Bal.BalanceTimeType = Mov.BalanceTimeType AND
DateDiff(DAY, #Date, Mov.Date) > 0 AND
-- Currency může být null a NULL = NULL nejde
COALESCE(Bal.CurrencyId, -1) = COALESCE(Mov.CurrencyId, -1)
) Mov(SumAmount)
SELECT aa AS a, aa AS b
FROM table1
WHERE quantity > 5
One way;
;with T (value) as (
select aa from table1 where quantity > 5
)
insert into #temptable
select value, value from T