Using SQL Server, I have...
AccDocumentItems Table:
SLId DL1Id DL2Id Debit Credit CurId ExchangeRate Cnt
------------------------------------------------------------------------------
S1 D1 D4 2000 0 1 1000 2
S1 D1 D4 0 6000 1 1500 4
S1 D1 D4 6000 0 1 1200 5
S2 D2 D4 4000 0 2 1000 4
S2 D2 D4 0 2000 2 1000 2
S2 D2 D4 3000 0 2 1500 2
I am trying to write a query in sql that group by CurId then substract Cnt column that has debit greater than 0 from Cnt Column that has Debit 0,for example row 1 to 3 has CurId 1 and row 1 has Debit greater than zero,then we have (2-4+5)=3 and row 4 to 6 has CurId 2 then we have (4-2+2)=4 finally I want sum of them 3*Last ExchangeRate in ExchangeRates Table, and 4*Last ExchangeRate in ExchangeRates Table, then sum of (3*Last ExchangeRate+4*Last ExchangeRate).
ExchangeRates Table:
CurrencyId EffectiveDate ExchangeRate
------------------------------------------------
1 2016-1-1 1000
2 2016-1-2 1200
2 2016-1-3 2000
1 2016-1-4 1500
result=(3*Last ExchangeRate+4*Last ExchangeRate)-((sum of Debit)-(sum
of Credit))
in this example Last ExchangeRate for CurrencyId 1 is 1500, and Last ExchangeRate for CurrencyId 2 is 2000 finally I want this result
result=(3*1500+4*2000)-(15000-8000)
This solution is based on your calculations and works only with 2 CurId's.
declare #cur_1 int = 1
declare #cur_2 int = 2
;with AccDocumentItems as (
select
*
from
(values
('S1','D1','D4',2000,0,1,1000,2)
,('S1','D1','D4',0,6000,1,1500,4)
,('S1','D1','D4',6000,0,1,1200,5)
,('S2','D2','D4',4000,0,2,1000,4)
,('S2','D2','D4',0,2000,2,1000,2)
,('S2','D2','D4',3000,0,2,1500,2)
) t (SLId, DL1Id, DL2Id, Debit, Credit, CurId, ExRate, Cnt)
)
, ExchangeRates as (
select
*
from
(values
(1,'2016-1-1',1000)
,(2,'2016-1-2',1200)
,(2,'2016-1-3',2000)
,(1,'2016-1-4',1500)
) t (CurrencyId, EffectiveDate, ParityRate)
)
select
sum(t.cnt * q.ParityRate) - sum(diff)
from
(
select
CurId, diff = sum(Debit) - sum(Credit), cnt = sum(cnt * case when Debit = 0 then -1 else 1 end)
from
AccDocumentItems
where
CurId in (#cur_1, #cur_2)
group by CurId
) t
join (
select
top 1 with ties *
from
ExchangeRates
order by row_number() over (partition by CurrencyId order by EffectiveDate desc)
) q on t.CurId = q.CurrencyId
This solution works for All CurId's.
Declare #Result int
Declare #DeCr int
Declare #Cur int
Set #DeCr = (
Select SUM(Debit)-SUM(Credit)
From dbo.AccDocumentItems
)
Set #Cur =
(
Select Sum(ParityRate * Zarib)
From
(
Select ExchangeRates.CurrencyId as cuur,ParityRate
From
(
Select Max(EffectiveDate) As MaxDate,CurrencyId
From dbo.ExchangeRates
Group by CurrencyId
)As Table1
left join
dbo.ExchangeRates
ON table1.currencyid = ExchangeRates.CurrencyId
And Table1.MaxDate = EffectiveDate
) As Table3
inner join
(
Select Curid
, sum(cnt*signs) As Zarib
From
(
Select CurId
, Cnt
, Case
When Debit = 0 Then -1
Else 1
End As Signs
From dbo.AccDocumentItems
) As Table2
Group by Curid
) As Table4
On Table3.cuur = Table4.Curid
)
Select #Cur - #DeCr
Declare #Result int
Declare #DeCr int
Declare #Cur int
Set #DeCr = (
Select SUM(Debit)-SUM(Credit)
From dbo.AccDocumentItems
)
Set #Cur =
(
Select Sum(ParityRate * Zarib)
From
(
Select ExchangeRates.CurrencyId as cuur,ParityRate
From
(
Select Max(EffectiveDate) As MaxDate,CurrencyId
From dbo.ExchangeRates
Group by CurrencyId
)As Table1
left join
dbo.ExchangeRates
ON table1.currencyid = ExchangeRates.CurrencyId
And Table1.MaxDate = EffectiveDate
) As Table3
inner join
(
Select Curid
, sum(cnt*signs) As Zarib
From
(
Select CurId
, Cnt
, Case
When Debit = 0 Then -1
Else 1
End As Signs
From dbo.AccDocumentItems
) As Table2
Group by Curid
) As Table4
On Table3.cuur = Table4.Curid
)
set #result = #Cur - #DeCr
Select #result
Related
Is it possible to make this in sql:
Have table with records:
ID LaborID OrderNr OrderStatusID OrderStatusDate
12990 3731573 OPT1814378 2 2018-05-28 09:35:30.123
13105 230687389 OPT1814378 1 2018-05-29 10:32:14.850
13106 230687389 OPT1814378 2 2018-05-29 10:52:14.403
13123 230480202 OPT1814378 1 2018-05-29 13:18:05.233
13130 230480202 OPT1814378 0 2018-05-29 13:29:17.360
12837 3731573 OPT1814089 2 2018-05-25 20:28:24.817
12906 10138504 OPT1814089 1 2018-05-26 10:41:18.680
12909 10138504 OPT1814089 2 2018-05-26 10:57:40.733
12913 10138504 OPT1814089 1 2018-05-26 11:41:48.387
12920 10138504 OPT1814089 0 2018-05-26 12:15:48.590
where
OrderStatusID
0 - End
1 - Begin
2 - pause
Need calculate working time from begin to pause (1->2) or from begin to end (1->0).
My problem is that there are some conditions that I have to adhere to:
If first record is 2 then ignore
Work begin always with 1
But can have more pause (1->2)
The last work end record everytime with 0
The result in this case will be:
OPT1814378 230687389 00:20:00
OPT1814378 230480202 00:11:12
OPT1814089 10138504 00:16:12
OPT1814089 10138504 00:34:00
Hopefully this is not that ugly.
; with
cte as
(
-- CTE for generating a sequence no
select *, rn = row_number() over (partition by OrderNr
order by OrderStatusDate)
from #table
),
cte2 as
(
-- Clean up invalid any rows and regenerate new sequence no
select ID, LaborID, OrderNr, OrderStatusID, OrderStatusDate,
rn = row_number() over (partition by OrderNr
order by OrderStatusDate)
from cte
where (rn = 1 and OrderStatusID = 1)
or rn >= 2
)
select OrderNr, LaborID,
convert(varchar(10),
dateadd(second,
datediff(second,
min(OrderStatusDate),
max(OrderStatusDate)),
0),
108)
from cte2
group by OrderNr,
LaborID,
(rn - 1) / 2
(rn - 1) / 2 will gives the value 0, 0, 1, 1, 2, 2 etc for grouping the rows two by two.
This one also works
;WITH CTE
AS (
SELECT row_number() OVER ( PARTITION BY ordernr ORDER BY id ) RN ,* FROM test_ti
)
,cte2
AS (
SELECT *
FROM cte c1
WHERE NOT EXISTS (
SELECT *
FROM cte c2
WHERE c1.id = c2.id
AND c2.rn = 1
AND c2.orderstatusid = 2
)
)
SELECT OrderNr
,LaborId
,TimeInterval
FROM ( SELECT DateDiff(MI, TIME, NxtTm) TimeInterval ,*
FROM (
SELECT * ,lead(TIME) OVER ( ORDER BY id ) NxtTm
FROM cte2
) x
WHERE orderstatusid <> 0
) y
WHERE orderstatusid = 1
I have a table in MS SQL Server, where are some null values in column "value"
Group ID Value
A 1 10
A 2
A 3
A 4 40
B 1
B 2 20
B 3 30
B 4
I want to update null values by not null in the same group with with the first higher ID, or if there is not any higher in same group, first lower. So the result should look like this.
Group ID Value
A 1 10
A 2 40
A 3 40
A 4 40
B 1 20
B 2 20
B 3 30
B 4 30
Thanks!
You can use windowed version of SUM function in order to determine islands of NULL valued records along with the record having the higher ID in the same group:
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp
FROM mytable
Output:
Group ID Value grp
-----------------------
A 4 40 1
A 3 30 2
A 2 NULL 2
A 1 NULL 2
B 4 40 1
B 3 NULL 1
B 2 20 2
B 1 10 3
You can now wrap the above query in a CTE and use another CTE to do the update:
;WITH CTE AS (
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp
FROM mytable
), ToUpdate AS (
SELECT [Group], ID, Value,
MAX(Value) OVER (PARTITION BY [Group], grp) AS group_value
FROM CTE
)
UPDATE ToUpdate
SET Value = group_value
WHERE Value IS NULL
Demo here
Edit:
The above query doesn't handle the edge case where the very last record within a Group slice is NULL. To handle this case as well you can use the following query:
;WITH CTE AS (
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID) AS grp2
FROM mytable
), ToUpdate AS (
SELECT [Group], ID, Value,
MAX(Value) OVER (PARTITION BY [Group], grp) AS group_value,
MAX(Value) OVER (PARTITION BY [Group], grp2) AS group_value2
FROM CTE
)
UPDATE ToUpdate
SET Value = COALESCE(group_value, group_value2)
WHERE Value IS NULL
Demo here
Please try this-
DATA GENERATION
DECLARE #T TABLE
(
GroupCd CHAR(1),
Id INT,
Value INT
)
INSERT INTO #T
VALUES('A',1,10),
('A',2,NULL),
('A',3,NULL),
('A',4,40),
('B',1,NULL),
('B',2,20),
('B',3,30),
('B',4,NULL)
SOLUTION
UPDATE a
SET a.Value = b.Value
FROM #T a
INNER JOIN
(
SELECT a.GroupCd,a.Id,Coalesce(a.Value,z.Value,z1.Value) Value
FROM #T a
OUTER APPLY
(
SELECT TOP 1 Value
FROM #T b
WHERE a.GroupCd = b.GroupCd
AND b.Value IS NOT NULL AND a.Id < b.Id
ORDER BY Id
)z
OUTER APPLY
(
SELECT TOP 1 Value
FROM #T b
WHERE a.GroupCd = b.GroupCd
AND b.Value IS NOT NULL AND a.Id > b.Id
ORDER BY Id DESC
)z1
)b ON a.GroupCd = b.GroupCd AND a.Id = b.Id
SELECT * FROM #T
OUTPUT
GroupCd Id Value
------- ----------- -----------
A 1 10
A 2 40
A 3 40
A 4 40
B 1 20
B 2 20
B 3 30
B 4 30
(8 rows affected)
You Can try This simple Method
DECLARE #T TABLE
(
GroupCd CHAR(1),
Id INT,
Value INT
)
INSERT INTO #T
VALUES('A',1,NULL),
('A',2,NULL),
('A',3,30),
('A',4,40),
('B',1,10),
('B',2,20),
('B',3,NULL),
('B',4,40)
SELECT
*,
NewVal = COALESCE(Value,(SELECT TOP 1 Value FROM #T WHERE GroupCd = T.GroupCd AND Id > T.Id AND Value IS NOT NULL ORDER BY Id ASC))
FROM #T T
My Result
update MY_TABLE set [value] = [newValue] from (
select [Group] [newGroup],
[Value] [newValue]
from (
select [Group], [Value],
row_number() over (partition by [group] order by [Id] desc) [rn]
from MY_TABLE
where [Value] is not null
) [a] where [rn] = 1
) where [Group] = [newGroup] and [Value] is null
Needs some help on the following:
Table #Data contains the Opening and Closing Stock for a product over 5 days
Table #BackData contains some post dated transactions
How can i Update the table #Data with a Running Total including a carry forward
CREATE TABLE #Data (
Prod VARCHAR(20)
,SDate DATE
,OStock INT
,CStock INT
)
CREATE TABLE #BackData (
Prod VARCHAR(20)
,SDate DATE
,CStock INT
)
INSERT INTO #Data
SELECT 'p1', '2016-06-06', 10, 10
UNION ALL
SELECT 'p1', '2016-06-07', 10, 14
UNION ALL
SELECT 'p1', '2016-06-08', 14, 13
UNION ALL
SELECT 'p1', '2016-06-09', 13, 13
UNION ALL
SELECT 'p1', '2016-06-10', 13, 11
INSERT INTO #BackData
SELECT 'p1', '2016-06-06', 2
UNION ALL
SELECT 'p1', '2016-06-07', 4
UNION ALL
SELECT 'p1', '2016-06-09', -1
UNION ALL
SELECT 'p1', '2016-06-10', -2
DROP TABLE #Data
DROP TABLE #BackData
Desired Output :
Prod| SDate |OStock |CStock|
p1 |2016-06-06 |10 |12 |
p1 |2016-06-07 |12 |16 |
p1 |2016-06-08 |16 |16 |
p1 |2016-06-09 |16 |15 |
p1 |2016-06-10 |15 |13 |
EDIT
This is what i had managed to write before i got the answer, using two updates because the actual table had too many columns to use in a single query.
UPDATE D
SET D.CStock = FL.NewCStock
FROM #Data D
INNER JOIN (
SELECT DT.Prod
,DT.SDate
,SUM(IIF(RwNm = 1, DT.CStock, 0) + ISNULL(BD.CStock, 0)) OVER (
PARTITION BY DT.Prod ORDER BY DT.SDate ROWS UNBOUNDED PRECEDING
) NewCStock
FROM (
SELECT Prod
,SDate
,CStock
,ROW_NUMBER() OVER (
PARTITION BY Prod ORDER BY SDate
) AS RwNm
FROM #Data
) DT
LEFT JOIN #BackData BD ON DT.Prod = DT.Prod
AND BD.SDate = DT.SDate
) FL ON D.Prod = FL.Prod
AND D.SDate = FL.SDate
UPDATE D
SET D.OStock = PV.NewOStock
FROM #Data D
INNER JOIN (
SELECT Prod
,SDate
,ISNULL(LAG(CStock) OVER (
PARTITION BY Prod ORDER BY SDate
), CStock) AS NewOStock
FROM #Data
) PV ON D.Prod = PV.Prod
AND D.SDate = PV.SDate
You can use the following query to UPDATE:
;WITH ToUpdate AS (
SELECT d1.OStock, d1.CStock,
COALESCE(LAG(d2.CStock2) OVER (PARTITION BY d2.Prod
ORDER BY d2.SDate),
d1.OStock) AS OStock2,
d2.CStock2
FROM #Data AS d1
JOIN (
SELECT d.Prod, d.SDate, d.OStock, d.CStock,
COALESCE(t.newCStock,
LAG(t.newCStock) OVER (PARTITION BY d.Prod
ORDER BY d.SDate)) AS CStock2
FROM #Data AS d
LEFT JOIN (
SELECT bd.Prod, bd.SDate,
drn.CStock + SUM(bd.CStock) OVER (PARTITION BY bd.Prod
ORDER BY bd.SDate) AS newCStock
FROM #BackData AS bd
INNER JOIN (
SELECT Prod, CStock,
ROW_NUMBER() OVER (PARTITION BY Prod ORDER BY SDate) AS rn
FROM #Data
) AS drn ON bd.Prod = drn.Prod AND drn.rn = 1
) AS t ON t.Prod = d.Prod AND t.SDate = d.SDate
) AS d2 ON d1.Prod = d2.Prod AND d1.SDate= d2.SDate
)
UPDATE ToUpdate
SET OStock = OStock2,
CStock = CStock2
This looks awfully convoluted, but I couldn't think of anything simpler.
Demo here
You can rebuild values in #Data table with the help of recursive CTE:
;WITH cte AS (
SELECT top 1 d.Prod,
d.SDate,
d.OStock,
d.OStock + b.CStock as CStock
FROM #Data d
LEFT JOIN #BackData b
ON b.Prod = d.Prod and b.SDate = d.SDate
ORDER BY d.SDate ASC
UNION ALL
SELECT c.Prod,
DATEADD(day,1,c.SDate),
c.CStock,
c.CStock + ISNULL(b.CStock,0)
FROM cte c
INNER JOIN #Data d
ON d.Prod = c.Prod AND d.SDate = DATEADD(day,1,c.SDate)
OUTER APPLY (SELECT CStock FROM #BackData b WHERE b.Prod = d.Prod and b.SDate = d.SDate) as b
)
SELECT *
FROM cte
Output:
Prod SDate OStock CStock
-------------------- ---------- ----------- -----------
p1 2016-06-06 10 12
p1 2016-06-07 12 16
p1 2016-06-08 16 16
p1 2016-06-09 16 15
p1 2016-06-10 15 13
To update #Data:
UPDATE d
SET OStock = c.OStock, CStock = c.CStock
FROM #Data d
INNER JOIN cte c
ON c.Prod = d.Prod AND c.SDate = d.SDate
Shouldn't the result be like :
Prod SDate OStock CStock
p1 2016-06-06 10 12
p1 2016-06-07 12 20 (#Data CStock 14 + #BakData 2 + 4)
p1 2016-06-08 20 19 (#Data CStock 13 + #BakData 2 + 4)
p1 2016-06-09 19 18 (#Data CStock 13 + #BakData 2 + 4 - 1)
p1 2016-06-10 18 14 (#Data CStock 11 + #BakData 2 + 4 - 1 -2)
This query will produce the above result
update d
set OStock = d.OStock + a.OAdj,
CStock = d.CStock + a.CAdj
from #Data d
cross apply
(
select OAdj = sum(case when Oflag = 1 then x.CStock else 0 end),
CAdj = sum(x.CStock)
from
(
select *, Oflag = case when x.SDate = d.SDate then 0 else 1 end
from #BackData x
where x.Prod = d.Prod
and x.SDate <= d.SDate
) x
) a
Based on your expected output, it seems that you are re-calculating the daily Opening / Closing balance based on the figure from 2016-06-06
Here is a solution that will gives you your expected output.
; with
cte as
(
select Prod, SDate, OStock, CStock,
rn = row_number() over (partition by Prod order by SDate)
from #Data
),
adj as
(
select Prod, SDate, CStock
from cte
where rn = 1
union all
select Prod, SDate, CStock
from #BackData
)
update d
set OStock = coalesce(o.OStock, d.OStock),
CStock = c.CStock
from #Data d
cross apply
(
select OStock = sum(x.CStock)
from adj x
where x.Prod = d.Prod
and x.SDate < d.SDate
) o
cross apply
(
select CStock = sum(x.CStock)
from adj x
where x.Prod = d.Prod
and x.SDate <= d.SDate
) c
Result :
p1 2016-06-06 10 12
p1 2016-06-07 12 16
p1 2016-06-08 16 16
p1 2016-06-09 16 15
p1 2016-06-10 15 13
I have a query below to allocated stock qty to match order qty based on order type. The problem is the stock qty is not updated.
DECLARE #tblOrder TABLE
(DealerCode NVARCHAR(50),
PartCode NVARCHAR(50),
OrderQty INT,
OrderType NVARCHAR(50)
)
INSERT INTO #tblOrder
( DealerCode,
PartCode,
OrderQty,
OrderType )
VALUES ('D1','A',19,'Urgent'),
('D2','B',10,'Normal'),
('D3','C',11,'HotLine'),
('D1','D',20,'Normal'),
('D2','E',12,'Normal'),
('D1','D',40,'Normal');
DECLARE #tblStock TABLE
(PartCode NVARCHAR(50),
StockQty INT)
INSERT INTO #tblStock
( PartCode,
StockQty)
VALUES ('A',20),
('B',15),
('C',9),
('D',30),
('E',0)
;WITH ordertemp AS (
select ord.dealercode,
ord.partcode,
ord.orderqty,
ord.ordertype,
RANK() OVER (ORDER BY case ord.ordertype when 'HotLine' then 1 when 'Urgent' then 2 else 3 end, ord.partcode, ord.dealercode) 'StockPriority',
sto.stockqty 'InitialStock'
from #tblorder ord
left outer join #tblstock sto
on ord.partcode = sto.partcode )
SELECT
Orders.dealercode,
Orders.partcode,
CASE WHEN Backlog.PriorQty > Orders.InitialStock THEN 0
ELSE Orders.InitialStock - Backlog.PriorQty END 'Stock',
Orders.orderqty,
CASE WHEN Backlog.PriorQty + Orders.OrderQty < Orders.InitialStock THEN Orders.OrderQty
WHEN Backlog.PriorQty > Orders.InitialStock THEN 0
ELSE Orders.InitialStock - Backlog.PriorQty END 'Allocated',
Orders.ordertype
FROM
ordertemp Orders
INNER JOIN
(
SELECT A.stockpriority, A.partcode, ISNULL(SUM(B.orderqty),0) 'PriorQty'
from ordertemp A
LEFT OUTER JOIN ordertemp B
on A.partcode = B.partcode
and A.stockpriority > B.stockpriority
group by A.stockpriority, A.partcode ) Backlog
ON Orders.stockpriority = Backlog.stockpriority
ORDER BY Orders.StockPriority
I got result:
dealercode partcode stock orderqty allocated ordertype
D3 C 9 11 9 HotLine
D1 A 20 19 19 Urgent
D2 B 15 10 10 Normal
D1 D 30 20 20 Normal
D1 D 30 40 30 Normal
D2 E 0 12 0 Normal
Actually, the stock (30) of partcode 'D' must be remain 10 after allocated 20.
Any idea please?
The Reason you get stock 30 is because your are using RANK for prioritization. RANK will allocate the same number to two order records if they have the same stock priority as defined by your condition ORDER BY case ord.ordertype when 'HotLine' then 1 when 'Urgent' then 2 else 3 end, ord.partcode, ord.dealercode. If you check the output of ordertemp you will see
dealercode partcode orderqty ordertype StockPriority InitialStock
D3 C 11 HotLine 1 9
D1 A 19 Urgent 2 20
D2 B 10 Normal 3 15
D1 D 20 Normal 4 30
D1 D 40 Normal 4 30
D2 E 12 Normal 6 0
Notice that the StockPriority of partcode D is 4 for both rows 4 and 5.
You can fix this by using ROW_NUMBER() instead of RANK() . You can also add orderqty in ROW_NUMBER() to specify if you want higher priority for smaller/larger orders if they have the same ordertype, partcode and dealercode.
Query with ROW_NUMBER()
DECLARE #tblOrder TABLE
(DealerCode NVARCHAR(50),
PartCode NVARCHAR(50),
OrderQty INT,
OrderType NVARCHAR(50)
)
INSERT INTO #tblOrder
( DealerCode,
PartCode,
OrderQty,
OrderType )
VALUES ('D1','A',19,'Urgent'),
('D2','B',10,'Normal'),
('D3','C',11,'HotLine'),
('D1','D',20,'Normal'),
('D2','E',12,'Normal'),
('D1','D',40,'Normal');
DECLARE #tblStock TABLE
(PartCode NVARCHAR(50),
StockQty INT)
INSERT INTO #tblStock
( PartCode,
StockQty)
VALUES ('A',20),
('B',15),
('C',9),
('D',30),
('E',0)
;WITH ordertemp AS (
select ord.dealercode,
ord.partcode,
ord.orderqty,
ord.ordertype,
ROW_NUMBER() OVER (ORDER BY case ord.ordertype when 'HotLine' then 1 when 'Urgent' then 2 else 3 end, ord.partcode, ord.dealercode) 'StockPriority',
sto.stockqty 'InitialStock'
from #tblorder ord
left outer join #tblstock sto
on ord.partcode = sto.partcode )
SELECT
Orders.dealercode,
Orders.partcode,
CASE WHEN Backlog.PriorQty > Orders.InitialStock THEN 0
ELSE Orders.InitialStock - Backlog.PriorQty END 'Stock',
Orders.orderqty,
CASE WHEN Backlog.PriorQty + Orders.OrderQty < Orders.InitialStock THEN Orders.OrderQty
WHEN Backlog.PriorQty > Orders.InitialStock THEN 0
ELSE Orders.InitialStock - Backlog.PriorQty END 'Allocated',
Orders.ordertype
FROM
ordertemp Orders
INNER JOIN
(
SELECT A.stockpriority, A.partcode, ISNULL(SUM(B.orderqty),0) 'PriorQty'
from ordertemp A
LEFT OUTER JOIN ordertemp B
on A.partcode = B.partcode
and A.stockpriority > B.stockpriority
group by A.stockpriority, A.partcode ) Backlog
ON Orders.stockpriority = Backlog.stockpriority
ORDER BY Orders.StockPriority
He's quite right above - when you first posted I had made the assumption you'd only have one entry per supplier per part / priority rather than duplicates :)
Note if you added orderquantity you would still face a problem if you had 2 entries with the same quantity in each.
I am using mssql 2008 R2,
i have below structure
create table #temp (
product int,
[order] int,
ord_qnty int
)
insert #temp
select 10 ,3,4
now, if ord_qnty is 4 , i want to select same product,order four times but in all four rows thevalue of ord_qnty should be 1 , i.e.
out put should be
Product order ord_qnty
10 3 1
10 3 1
10 3 1
10 3 1
If you have a numbers table, you can use that. If not, you can generate one:
;with Numbers(n) as (
select ROW_NUMBER() OVER (ORDER BY object_id) from sys.objects
)
select product,[order],1 as ord_qnty
from #temp t inner join Numbers num
on t.ord_qnty >= num.n
(In my nearly empty scratch database, the ROW_NUMBER() generates 77 rows. If that's not going to be enough, you can introduce cross-joins or use other tricks to generate more numbers, or you can create and populate a permanent numbers table)
Try this one -
Query:
DECLARE #temp TABLE
(
product INT
, [order] INT
, ord_qnty INT
)
INSERT #temp(product, [order], ord_qnty)
SELECT 10, 3, 4
SELECT
t.product
, t.[order]
, ord_qnty = 1
FROM #temp t
JOIN [master].dbo.spt_values sv ON t.ord_qnty > sv.number
WHERE sv.[type] = 'p'
SELECT
t.product
, t.[order]
, ord_qnty = 1
FROM #temp t
JOIN (
SELECT number = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM sys.system_parameters p
) sv ON t.ord_qnty >= sv.number
Output:
product order ord_qnty
----------- ----------- -----------
10 3 1
10 3 1
10 3 1
10 3 1
Query Cost:
For any "millions value":
SET NOCOUNT ON;
DECLARE #numbers TABLE (number INT)
DECLARE #temp TABLE
(
product INT
, [order] INT
, ord_qnty INT
)
INSERT #temp(product, [order], ord_qnty)
SELECT 10, 3, 4
DECLARE
#i BIGINT = 1
, #max BIGINT = (
SELECT MAX(ord_qnty)
FROM #temp
)
WHILE (#i <= #max) BEGIN
INSERT INTO #numbers (number)
VALUES (#i), (#i+1), (#i+2), (#i+3), (#i+4), (#i+5), (#i+6), (#i+7), (#i+8), (#i+9)
SELECT #i += 10
END
SELECT
t.product
, t.[order]
, ord_qnty = 1
FROM #temp t
CROSS JOIN (
SELECT *
FROM #numbers
WHERE number < #max + 1
) t2