Using a loop in SQL to populate the table (SQL Server) - sql

I am quite new with SQL and loops especially and need some help with the following problem.
I have a table like this:
SpotID EventID MaxTemp
123 1 45
236 1 109
69 1 18
123 2 216
236 2 29
69 2 84
123 3 91
236 3 457
69 3 280
I would like to generate a new table with the following output:
SpotID Over30 Over70 Over100
123 3 2 1
236 2 2 2
69 2 2 1
So what i am after is the count of how many times did the temperature exceed the limits of 30, 70 and 100 per SpotID for different EventIDs.
Is there a way to do this with a loop? My data set is obviously bigger and I am curious if how could i use something efficient.
Thank you very much.
Mike

You just need conditional aggregation:
select spotid,
sum(case when maxtemp > 30 then 1 else 0 end) as over_30,
sum(case when maxtemp > 70 then 1 else 0 end) as over_70
sum(case when maxtemp > 100 then 1 else 0 end) as over_100
from likethis
group by spotid;

If you just want to learn how to use loops....
DECLARE #DATA TABLE (
SpotID INT,
EventID INT,
MaxTemp INT
);
DECLARE #NEWDATA TABLE (
SpotID INT,
T30 INT,
T90 INT,
T100 INT
);
DECLARE
#SPOT AS INT,
#T30 AS INT,
#T90 AS INT,
#T100 AS INT;
INSERT INTO #DATA VALUES
(123, 1, 45 ),
(236, 1, 109),
(69 , 1, 18 ),
(123, 2, 216),
(236, 2, 29 ),
(69 , 2, 84 ),
(123, 3, 91 ),
(236, 3, 457),
(69 , 3, 280);
DECLARE STATION CURSOR FOR SELECT SpotID FROM #DATA GROUP BY SpotID;
OPEN STATION;
FETCH NEXT FROM STATION INTO #SPOT;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #T30 = 0;
SET #T90 = 0;
SET #T100 = 0;
SELECT
#T30 = SUM(CASE WHEN MaxTemp > 30 AND MaxTemp < 70 THEN 1 ELSE 0 END),
#T90 = SUM(CASE WHEN MaxTemp >= 70 AND MaxTemp < 100 THEN 1 ELSE 0 END),
#T100 = SUM(CASE WHEN MaxTemp >= 100 THEN 1 ELSE 0 END)
FROM #DATA WHERE SpotID = #SPOT
INSERT INTO #NEWDATA VALUES (#SPOT,#T30,#T90,#T100)
FETCH NEXT FROM STATION INTO #SPOT;
END;
CLOSE STATION;
DEALLOCATE STATION;
SELECT * FROM #NEWDATA
Not anyway I would write the code requested, but this example shows how to create table variables, a simple cursor for looping, and writing to answers to variables that are loaded into a new table.
A lot of moving parts but it can give you insight to doing loops.

One minor change to the previous post, my version only counts within each temp range, else the lower temps will count most temps not temps in that range.
DECLARE #DATA TABLE (
SpotID INT,
EventID INT,
MaxTemp INT
)
INSERT INTO #DATA VALUES
(123, 1, 45 ),
(236, 1, 109),
(69 , 1, 18 ),
(123, 2, 216),
(236, 2, 29 ),
(69 , 2, 84 ),
(123, 3, 91 ),
(236, 3, 457),
(69 , 3, 280)
SELECT
SpotID,
SUM(CASE WHEN MaxTemp > 30 AND MaxTemp < 70 THEN 1 ELSE 0 END) AS OVER_30,
SUM(CASE WHEN MaxTemp >= 70 AND MaxTemp < 100 THEN 1 ELSE 0 END) AS OVER_70,
SUM(CASE WHEN MaxTemp >= 100 THEN 1 ELSE 0 END) AS OVER_100
FROM
#DATA
GROUP BY
SpotID

Related

pivot multi column and mutil row

this is my origin data:
ID New LikeNew Old Warehouse
1 10 100 20 LA
1 12 130 40 CA
2 90 200 10 LA
2 103 230 30 CA
i want to get the following format:
ID LA_new LA_likeNew LA_Old CA_New CA_LikeNew CA_Old
1 10 100 20 12 130 40
2 90 200 10 103 230 30
I can only pivot on each column but can not do on all 3 columns(New, LikeNew, Old) , so how can I do that?
You can accomplish this by using conditional logic to create your fields and grouping:
select id,
max(case when warehouse = 'LA' then new else null end) LA_New,
max(case when warehouse = 'LA' then likenew else null end) LA_likeNew,
max(case when warehouse = 'LA' then old else null end) LA_Old,
max(case when warehouse = 'CA' then new else null end) CA_New,
max(case when warehouse = 'CA' then likenew else null end) CA_likeNew,
max(case when warehouse = 'CA' then old else null end) CA_Old
from yourtable
group by id
Alternatively, you can use WITH Common Table Expression
DECLARE #T AS TABLE
(
id INT ,
New INT ,
likeNew INT ,
old INT ,
Warehouse VARCHAR(50)
)
INSERT INTO #T
( id, New, likeNew, old, Warehouse )
VALUES ( 1, 10, 100, 20, 'LA' ),
( 1, 12, 130, 40, 'CA' ),
( 2, 90, 200, 10, 'LA' ),
( 2, 103, 230, 30, 'CA' );
WITH cte
AS ( SELECT *
FROM #T
WHERE Warehouse = 'LA'
),
cte1
AS ( SELECT *
FROM #T
WHERE Warehouse = 'CA'
)
SELECT a.id ,
a.new [LA_New] ,
a.likeNew [LA_LikeNew] ,
a.Old [LA_Old] ,
b.new [CA_New] ,
b.likeNew [CA_LikeNew] ,
b.Old [CA_Old]
FROM cte A
JOIN cte1 B ON a.id = b.id
Result:
id LA_New LA_LikeNew LA_Old CA_New CA_LikeNew CA_Old
----------- ----------- ----------- ----------- ----------- ----------- -----------
1 10 100 20 12 130 40
2 90 200 10 103 230 30

How to optimize the query which is taking too much time

In this query, i am calling a function "fnGetPoolWinner" in the below query 2-3 times,
which i think slows down its performance or multiple case statements is the reason.
It takes time around 00:01:39.
I have tried options like creating indxes in the table and creating Common Table Expression and then using that query, but haven't found any solution to reduce it's time.
DECLARE #TournamentId INT = 1
DECLARE #TournamentName AS NVARCHAR(MAX)
SELECT #TournamentName = TournamentName FROM Tournaments WHERE TournamentId = #TournamentId
SELECT
(SELECT CustomerIds FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,#TournamentId,
(CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END))) AS [AccountNumber],
#TournamentName AS TournamentName,
(CASE
WHEN SET_1.GAMES= 63
THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
WHEN SET_1.GAMES= 31
THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
WHEN SET_1.GAMES= 15
THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
ELSE ''
END) AS [PoolName],
(SELECT BracketNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,#TournamentId,
(CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END))) AS GroupEntries,
'Public' AS Access,
COUNT(SET_1.BracketId) AS Members,
COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize,
(SELECT WinnerNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,#TournamentId,
(CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END))) AS WinnersName,
(CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END) AS RoundId,
SET_1.BracketBettingAmount AS BettingAmount
FROM
(SELECT BR.BracketId,
BracketBettingAmount,
(SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES
FROM Brackets AS BR WHERE BR.BracketTournamentId = #TournamentId AND BR.IsDeleted = 0) SET_1 WHERE SET_1.GAMES > 0
GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES HAVING SET_1.BracketBettingAmount IN (1,5,10,25)
try this, not tested
DECLARE #TournamentId INT = 1
with SET_1 as (
SELECT BR.BracketId, BracketBettingAmount as BettingAmount, W.GAMES, TN.TournamentName,
case W.GAMES
WHEN 63 THEN 1
WHEN 31 THEN 2
WHEN 15 THEN 3
ELSE 0 END as IDGAME,
CASE W.GAMES
WHEN 63 THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
WHEN 31 THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
WHEN 15 THEN 'GENERAL POOL SWEET 16 $' +CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
ELSE '' END AS PoolName,
TN.TournamentId
FROM Brackets AS BR
cross apply
(
SELECT COUNT(*) GAMES FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId
) W
inner join Tournaments TN on BR.BracketTournamentId=TN.TournamentId
WHERE BR.IsDeleted = 0 and BracketBettingAmount IN (1,5,10,25) and W.GAMES>0 and TN.TournamentId = #TournamentId
),
NbBracketId as ( select NbBracketId, count(*) Nb from SET_1 group by NbBracketId)
SELECT
Y.CustomerIds AccountNumber, X.TournamentName, X.PoolName, Y.BracketNames AS GroupEntries, 'Public' AS Access,
Z.NB AS Members, Z.NB*X.BettingAmount AS CurrentPoolPrize, Y.WinnerNames, X.IDGAME AS RoundId, X.BettingAmount
FROM SET_1 X
outer apply DBO.fnGetPoolWinner(SET_1.BracketBettingAmount, SET_1.TournamentId, SET_1.IDGAME) as Y
inner join NbBracketId Z on X.BracketId=Z.BracketId
DBO.fnGetPoolWinner can be optmize itself.
try this approach,
DECLARE #TournamentId INT = 1
DECLARE #TournamentName AS NVARCHAR(MAX)
SELECT #TournamentName = TournamentName FROM Tournaments WHERE TournamentId = #TournamentId
select #TournamentName TournamentName,
CustomerIds AS [AccountNumber]
,(CASE
WHEN SET_1.GAMES= 63
THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
WHEN SET_1.GAMES= 31
THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
WHEN SET_1.GAMES= 15
THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
ELSE ''
END) AS [PoolName]
,ca.BracketNames as GroupEntries
'Public' AS Access,
COUNT(SET_1.BracketId) AS Members,
COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize
,WinnerNames as WinnersName
, (CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END) AS RoundId,
SET_1.BracketBettingAmount AS BettingAmount
FROM
(SELECT BR.BracketId,
BracketBettingAmount,
(SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES
FROM Brackets AS BR WHERE BR.BracketTournamentId = #TournamentId AND BR.IsDeleted = 0) SET_1
WHERE SET_1.GAMES > 0
GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES
HAVING SET_1.BracketBettingAmount IN (1,5,10,25)
cross apply(SELECT CustomerIds,BracketNames,WinnerNames
FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,#TournamentId,
(CASE
WHEN SET_1.GAMES= 63
THEN 1
WHEN SET_1.GAMES= 31
THEN 2
WHEN SET_1.GAMES= 15
THEN 3
ELSE 0
END)) )ca

SQL Server : data between specific range

I have a data which is something like this
stories value
--------------------------
0 2194940472.78964
1 1651820586.1447
2 627935051.75
3 586994698.4272
4 89132137.57
5 134608008
6 40759564
7 0
8 0
10 0
11 0
12 0
13 26060602
17 0
18 0
19 84522335
20 316478066.045
24 0
I want to sum it up as per the range
Output which I am expected
stories value
0-3 125201021
4-7 215453123
8-12 453121545
12-max(numstories) 21354322
I tried this but not able to figure it out what is wrong
select t.NumStories, SUM(t.bldnvalue)
from
(select
a.NumStories,
case
when a.NumStories between 0 and 3 then sum(a.BldgValue)
when a.NumStories between 4 and 7 then sum(a.BldgValue)
when a.NumStories between 8 and 12 then sum(a.BldgValue)
when a.NumStories between 13 and max(a.NumStories) then sum(a.BldgValue)
end as bldnvalue
from
dbo.EDM_CocaCola_Coca_Cola_Company_1_1 a
group by
a.NumStories) t
group by
t.NumStories
With this query I am getting this output
NumStories value
-------------------------------
0 2194940472.78964
3 586994698.4272
12 0
6 40759564
7 0
1 1651820586.1447
24 0
18 0
10 0
4 89132137.57
19 84522335
13 26060602
5 134608008
2 627935051.75
17 0
11 0
20 316478066.045
8 0
I like this result, I tried to use the BIN concept. I think the only issue would be with your max bin. I don't understand how you got your output sums. the first records value is '2,194,940,472.78964' which is bigger than your value in 0-3 bin
if OBJECT_ID('tempdb..#Test') is not null
drop table #Test;
Create table #Test (
Stories int
, Value float
)
insert into #Test
values
(0 , 2194940472.78964)
, (1 , 1651820586.1447 )
, (2 , 627935051.75 )
, (3 , 586994698.4272 )
, (4 , 89132137.57 )
, (5 , 134608008 )
, (6 , 40759564 )
, (7 , 0 )
, (8 , 0 )
, (10, 0 )
, (11, 0 )
, (12, 0 )
, (13, 26060602 )
, (17, 0 )
, (18, 0 )
, (19, 84522335 )
, (20, 316478066.045 )
, (24, 0 )
if OBJECT_ID('tempdb..#Bins') is not null
drop table #Bins;
create Table #Bins(
Label varchar(20)
, Min int
, Max int
)
insert into #Bins values
('0-3', 0, 3)
, ('4-7', 4, 7)
, ('8-12', 8, 12)
, ('13 - Max', 13, 999999999)
Select b.Label
, sum(t.Value) as Value
from #Test t
join #Bins b
on t.stories between b.Min and b.Max
Group by b.Label
order by 1
Output:
Label Value
-------------------- ----------------------
0-3 5061690809.11154
13 - Max 427061003.045
4-7 264499709.57
8-12 0
Just build the grouping string first that you want and group by that variable.
select
case
when a.NumStories between 0 and 3 then '0-3'
when a.NumStories between 4 and 7 then '4-7'
when a.NumStories between 8 and 12 then '8-12'
when a.NumStories >= 13 then '13-max'
end as stories,
sum(a.BldgValue) as value
from
dbo.EDM_CocaCola_Coca_Cola_Company_1_1 a
group by 1;
If you really want to print the max too, then you can put in a subquery in the "13-max" line as (SELECT MAX(BldgValue) FROM dbo.EDM_CocaCola_Coca_Cola_Company_1_1)
You can try this:
SELECT '0-3' AS stories,
SUM(value) AS value
FROM dbo.EDM_CocaCola_Coca_Cola_Company_1_1
WHERE stories BETWEEN 0 AND 3
UNION ALL
SELECT '4-7' AS stories,
SUM(value) AS value
FROM dbo.EDM_CocaCola_Coca_Cola_Company_1_1
WHERE stories BETWEEN 4 AND 7
UNION ALL
...
Here is solution with CTE that should work for any data set, without copying the code.
declare #YourTable table(stories int, value money)
declare #GroupMemberCount int=4
insert #YourTable (stories,value) values (0,5),(1,10),(2,11),(3,7),(4,18),(5,13),(7,15)
;with cte as
(
select c.stories+v.i*#GroupMemberCount FirstGroupMember, c.stories+v.i*#GroupMemberCount+#GroupMemberCount -1 LastGroupMember
,CAST(c.stories+v.i*#GroupMemberCount as varchar(50))
+'-'+CAST(c.stories+v.i*#GroupMemberCount+#GroupMemberCount -1 as varchar(50))GroupName
from (select MIN(stories) stories from #YourTable) c
cross join (values (0),(1),(2),(3),(4)/* and so on */) v(i)
where exists (select * from #YourTable yt where yt.stories>=c.stories+v.i*3)
)
select c.GroupName, SUM(yt.value)
from cte c
JOIN #YourTable yt ON yt.stories BETWEEN c.FirstGroupMember AND C.LastGroupMember
GROUP BY c.GroupName

Nested CASE in SQL

TABLE1:
ARTIKEL SUPPLIERID SALE_SUM_PIECES
TV SONY 7
TABLE2:
ROW_ID ARTIKEL SUPPLIERID PIECES
1 TV SONY 6
2 TV SONY 10
3 TV SONY 6
4 TV SONY 14
5 TV SONY 18
6 TV SONY 4
I need to subtract value X=23 on TABLE2."PIECES", only when the value TABLE1."SALE_SUM_PIECES" is less than the SUM of "PIECES" in TABLE2. For example: the value of TABLE1."SALE_SUM_PIECES" is 7. NOw I need to check at which row the value 7 goes less than the SUM of TABLE2."PIECES".In the below example the first row in TABLE2 is not valid because 7 is greater than 6. But the second row in TABLE2 is valid since the SUM OF "PIECES" from row1 and row2 in TABLE2 i.e 6+10=16 is greater than 7. So, I need to subtract value of X=23 from the second row to the following rows in TABLE2.
The query I have is as follows:
SELECT "SUPPLIERID", "ARTIKEL",
(case when ( cumulativesum - (select "SALE_SUM_PIECES" from T1 where T1."SUPPLIERID"=T2."SUPPLIERID" and T1."ARTIKEL" = T2."ARTIKEL" )) <= 0
then NULL
when ( cumulativesum - (select "SALE_SUM_PIECES" from TABLE1 T1 where T1."SUPPLIERID"=T2."SUPPLIERID" and T1."ARTIKEL" = T2."ARTIKEL" )) > 0
then
(case when #x - cumulativesum <= 0 and #x - (cumulativesum -PIECES) > 0
then 0
when #x - "cumulativesum" <= 0
then NULL
else #x - "cumulativesum"
end) as "VALUE_DRILL_DOWN"
from (SELECT T1."ARTIKEL", T1."SUPPLIERID", T1.PIECES
(select sum("PIECES")
from EXAMPLE_TABLE T2
where T2."ROW_ID" <= T1."ROW_ID" and T2."SUPPLIERID" = T1."SUPPLIERID" and T2."ARTIKEL"=T1."ARTIKEL"
) as "cumulativesum"
from EXAMPLE_TABLE T1
)
When I execute the above query I get the result as follows:
ROW_ID ARTIKEL SUPPLIERID PIECES VALUE_DRILL_DOWN
1 TV SONY 6 NULL
2 TV SONY 10 7
3 TV SONY 6 1
4 TV SONY 14 0
5 TV SONY 18 Null
6 TV SONY 4 Null
But I expect a result to be as follows:
ROW_ID ARTIKEL SUPPLIERID PIECES VALUE_DRILL_DOWN
1 TV SONY 6 NULL
2 TV SONY 10 13
3 TV SONY 6 7
4 TV SONY 14 0
5 TV SONY 18 Null
6 TV SONY 4 Null
I want the subtraction of ´X=23´ to start from the row in TABLE2 where the condition TABLE1."SALE_SUM_PIECES" < TABLE2."PIECES" i.e from row2. Any suggestions?
Thanks in advance.
The below solution gives the desired results. See SqlFiddle
1 TV SONY 922 6 110 2.50 NULL
2 TV SONY 922 10 80 1.00 13
3 TV SONY 922 6 65 1.50 7
4 TV SONY 922 14 95 1.50 0
5 TV SONY 922 18 95 1.50 NULL
6 TV SONY 922 4 95 1.50 NULL
DECLARE #x INT = 23
; WITH cte AS
(
SELECT t2.*, t1.SALE_SUM_PIECES,
CASE
WHEN SUM(t2.PIECES) OVER (PARTITION BY t2.ARTIKEL, t2.SUPPLIERID ORDER BY ROW_ID) < t1.SALE_SUM_PIECES THEN 'None'
ELSE t2.ARTIKEL + t2.SUPPLIERID
END AS GroupId
FROM #Table2 t2
JOIN #Table1 t1 ON t2.ARTIKEL = t1.ARTIKEL AND t2.SUPPLIERID = t1.SUPPLIERID
),
cumulative AS
(
SELECT *, SUM(PIECES) OVER (PARTITION BY GroupId ORDER BY ROW_ID) AS CumulativeSum
FROM cte
)
SELECT ROW_ID, ARTIKEL, SUPPLIERID, ORGID, PIECES, COSTPRICE, DISCOUNT,
CASE
WHEN CumulativeSum < SALE_SUM_PIECES THEN NULL
WHEN #x - CumulativeSum <= 0 AND #x - (CumulativeSum - PIECES) > 0 THEN 0
WHEN #x - CumulativeSum <= 0 THEN NULL
ELSE #x - CumulativeSum
END AS VALUE_DRILL_DOWN
FROM cumulative
I'm not 100% sure what the expected calulation for VALUE_DRILL_DOWN is supposed to be.
You've said that for a valid row, it should be (sum of all rows at or above row) - 23
In this case the following code should work, but it gives different numbers from your expected results.
I've used a self-joining common table expression to work out the cumulative sums of the rows as you count up .
The (total of all rows at or above) is equal to the (total) - (cumulative sum at row before)
Therefore the following code should be correct...
DECLARE #table1 TABLE(ARTIKEL NVARCHAR(50), SUPPLIERID NVARCHAR(50), ORGID INT,
STORE INT, SALE_SUM_PIECES INT, [DATE] DATETIME)
DECLARE #table2 TABLE(ROW_ID INT, ARTIKEL NVARCHAR(50), SUPPLIERID NVARCHAR(50),
ORGID INT, PIECES INT, COSTPRICE MONEY, DISCOUNT DECIMAL(9,5))
DECLARE #x INT = 23
DECLARE #SumOfAll INT
INSERT #table1
( ARTIKEL , SUPPLIERID , ORGID , STORE , SALE_SUM_PIECES , [DATE] )
VALUES ( 'TV', 'SONY', 922,100,7 ,'2014-01-01' )
INSERT #table2
(ROW_ID, ARTIKEL , SUPPLIERID , ORGID , PIECES , COSTPRICE , DISCOUNT )
VALUES (1, 'TV', 'SONY', 922, 6, 110, 2.5 ),
(2, 'TV', 'SONY', 922, 10 , 80, 1 ) ,
(3, 'TV', 'SONY', 922, 6 , 65 , 1.5 ) ,
(4, 'TV', 'SONY', 922, 14 , 95 , 1.5 ),
(5, 'TV', 'SONY', 922, 18 , 95 , 1.5 ),
(6, 'TV', 'SONY', 922, 4 , 95 , 1.5 )
SELECT #SumOfAll = SUM(PIECES) FROM #table2 AS t
;WITH t2C AS (
SELECT ROW_ID, PIECES AS [cumulativeSum]
FROM #table2 AS t
WHERE ROW_ID = 1 -- assume starting at 1
UNION ALL
SELECT t.ROW_ID, t.PIECES + cumulativeSum AS [cumlativeSum]
FROM #table2 AS t
JOIN t2C ON t2C.ROW_ID + 1 = t.ROW_ID --assume rowIDs are sequential
)
SELECT
t2.ROW_ID,
t1.SUPPLIERID,
t1.ORGID,
t2.PIECES,
t2.COSTPRICE,
t2.DISCOUNT,
CASE WHEN t2C.cumulativeSum - t1.SALE_SUM_PIECES <= 0 THEN NULL
ELSE
CASE
WHEN #x - t2C.cumulativeSum <= 0
AND #x - (t2C.cumulativeSum - t2.PIECES) > 0 THEN 0
WHEN #x - t2C.cumulativeSum <= 0 THEN NULL
ELSE (#SumOfAll - t2cPrev.cumulativeSum) - #x
END
END AS [VALUE_DRILL_DOWN]
FROM t2C
LEFT JOIN t2C AS t2cPrev ON t2cPrev.ROW_ID = t2C.ROW_ID - 1
JOIN #table2 AS t2 ON t2.ROW_ID = t2C.ROW_ID
JOIN #table1 AS t1 ON t1.SUPPLIERID = t2.SUPPLIERID AND t1.ARTIKEL = t2.ARTIKEL
However this gives:
ROW_ID SUPPLIERID ORGID PIECES COSTPRICE DISCOUNT VALUE_DRILL_DOWN cumulativeSum sumOfRowsOnOrAfter
1 SONY 922 6 110.00 2.50000 NULL 6 NULL
2 SONY 922 10 80.00 1.00000 29 16 52
3 SONY 922 6 65.00 1.50000 19 22 42
4 SONY 922 14 95.00 1.50000 0 36 36
5 SONY 922 18 95.00 1.50000 NULL 54 22
6 SONY 922 4 95.00 1.50000 NULL 58 4
EDIT:
SQL Fiddle by WiiMaxx
select
*,
case when 23 - sum(c) over (order by row_id) >= 0
then 23 - sum(c) over (order by row_id)
when 23 - sum(c) over (order by row_id) + pieces > 0
then 0
end value_drill_down
from (
select *,
case when sum(pieces) over (order by row_id) >= (select sale_sum_pieces from t1)
then pieces
end c
from t2) x;

Update Query with Condition in SQL

I have a table that has 2 columns and i am trying to update another table based on these criteria:
Set the flag to 'Good' for the most duplicate keys in the Main_Key column for the same GROUP_KEY (Note we can have different Main_Keys for any GROUP_KEY)
Set the flag to 'Bad' for the least duplicate keys in the Main_Key column for the same GROUP_KEY
Set the flag to 'Don't Use' if the different Main_Keys are equal for the same GROUP_KEY
HERE IS MY TABLE
GROUP_KEY MAIN_KEY
22 4
22 4
22 55
22 55
22 55
22 55
10 10
10 10
18 87
18 22
18 22
HERE IS THE DESIRED RESULT AFTER THE UPDATE
GROUP_KEY MAIN_KEY FLAG
22 4 Bad
22 4 bad
22 55 Good
22 55 Good
22 55 Good
22 55 Good
10 10 Don't Use
10 10 Don't Use
18 87 Bad
18 22 Good
18 22 Good
I only know how to do just normal update query but not where even to start this logic. thnx for the help
Use:
declare #t table(GROUP_KEY int, MAIN_KEY int)
insert #t values
(22, 4),
(22, 4),
(22, 55),
(22, 55),
(22, 55),
(22, 55),
(10, 10),
(10, 10),
(18, 87),
(18, 22),
(18, 22)
select t.*, b.flag
from #t t
join
(
select a.GROUP_KEY, a.MAIN_KEY
,
case
when a.GROUP_KEY = a.MAIN_KEY
then 'Don''t Use'
when a.count = MAX(a.count) over(partition by a.GROUP_KEY)
then 'Good'
else 'Bad'
end [flag]
from
(
select t.GROUP_KEY, t.MAIN_KEY, COUNT(*) [count]
from #t t
group by t.GROUP_KEY, t.MAIN_KEY
)a
)b
on b.GROUP_KEY = t.GROUP_KEY and b.MAIN_KEY = t.MAIN_KEY
Output:
GROUP_KEY MAIN_KEY flag
----------- ----------- ---------
10 10 Don't Use
10 10 Don't Use
18 22 Good
18 22 Good
18 87 Bad
22 4 Bad
22 4 Bad
22 55 Good
22 55 Good
22 55 Good
22 55 Good
Update:
Assuming you have flag column in your table:
update #t
set flag = b.flag
from #t t
join
(
select a.GROUP_KEY, a.MAIN_KEY
,
case
when a.GROUP_KEY = a.MAIN_KEY
then 'Don''t Use'
when a.count = MAX(a.count) over(partition by a.GROUP_KEY)
then 'Good'
else 'Bad'
end [flag]
from
(
select t.GROUP_KEY, t.MAIN_KEY, COUNT(*) [count]
from #t t
group by t.GROUP_KEY, t.MAIN_KEY
)a
)b
on b.GROUP_KEY = t.GROUP_KEY and b.MAIN_KEY = t.MAIN_KEY