Need to arrange a record using while loop - sql

While fetching details using while loop I am not able to get it as I want. What I want is to apply a loop and get details of each date. I am using SQL 2008.
Set #i = 1;
While (#NoOfDays >= #i)
Begin
SET #ManufactureQty = (Select isnull(SUM(Quantity),0) as Manufactured from IGN1 inner join OIGN on (OIGN.DocEntry = IGN1.DocEntry)
inner join OITM on (OITM.ItemCode = IGN1.ItemCode)
where Convert(Date,Cast(OIGN.DocDate as DATE)) = Convert(Date,DATEADD(d, #i, #date)) and OITM.ItmsGrpCod = #ItemGroup)
Select #i as D,OpeningBalance = case
when #i > 1 then ((isnull(SUM(OINM.InQty),0)-isnull(SUM(OINM.OutQty),0)) + ((isnull(SUM(OINM.InQty),0)-isnull(SUM(OINM.OutQty),0))))
when #i = 1 then (isnull(SUM(OINM.InQty),0)-isnull(SUM(OINM.OutQty),0))
end
,
isnull(#ManufactureQty,0) as Manufacture
From OITM
Inner Join OINM On (OINM.ItemCode = OITM.ItemCode and Convert(Date,Cast(OINM.DocDate as DATE)) = Convert(Date,DATEADD(d, #i, #date))) --and Convert(Date,Cast(OINM.DocDate as DATE)) > Convert(Date,'2014-05-01'))
Where OITM.ItmsGrpCod = #ItemGroup group by OINM.DocDate
SET #i = #i + 1
End
It Gives
D OpeningBalance Manufacture
1 123 23
D OpeningBalance Manufacture
2 143 773
D OpeningBalance Manufacture
3 126 27
.
But I need it like
D OpeningBalance Manufacture
1 123 23
2 143 773
3 126 27
.

Before loop:
create table #results (D int, OpeningBalance Int, Manufacture Int)
in loop
begin
insert into #results ...
select ...
end
--after
select * from #results

Related

Concate string into temp table in cursor

I have a temp table structure #temp2 like this
route total driverID
------------------------
10B 300
7B 400
and would like to add the driverID column with a result like 5555, 68989
to do this, I use the cursor to loop another table look like this
driverID routeNo
-------------------
5555 10B
68989 10B
72000 7B
Here is the code
declare #driverID varchar(max)
declare #routeNew varchar(20)
DECLARE brand_cursor CURSOR FOR
select distinct driver_id, route_number from [dbcwl].[dbo].[collection_deduction_summary]
where YEAR(trans_date) = #year
and MONTH(trans_date) = #month
and route_number in (select actual_route from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
and vehicle_id in (select vehicle_id from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
group by route_number, driver_id
OPEN brand_cursor
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
WHILE ##FETCH_STATUS = 0
BEGIN
--update #temp2
update #temp2 set driverID += ','+ #driverID where routeNo = #routeNew;
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
END
CLOSE brand_cursor;
DEALLOCATE brand_cursor;
sadly, I got the driverID column is null
and would like to have finalized temp table look like this:
route total driverID
------------------------
10B 300 5555,68989
7B 400 72000
;with cte as -- Step 1: Get all Driver Ids by routeNo
(
SELECT routeNo, driverID =
STUFF((SELECT DISTINCT ', ' + CAST(driverID AS NVARCHAR(100))
FROM #A b
WHERE b.routeNo = a.routeNo
FOR XML PATH('')), 1, 2, '')
FROM #A a
GROUP BY routeNo
)
update b -- Step 2: Update driverID accordingly.
set driverID = cte.driverID
from #B b
inner join cte on b.route = cte.routeNo
Result here
You can string_agg():
update t
set t.driverID = ot.drivers
from #temp2 t join
(select ot.routeNo, string_agg(driverID, ',') as drivers
from othertable ot
group by ot.routeNo
) ot
on t.routeNo = ot.routeNo;

Find the association of values in the table

I have one table as shown below.
Table:
LinkA linkB
--------------------
1 10
10 2
2 5
4 7
6 7
7 3
8 2
3 9
I want to find the association of values in the table. It will link to any row that has one of its two values and continue with the newly linked row.
Like that :
Row 1 (1,10) -> Row 2 (10,2) -> Row 3 (2,5) -> Row 7 (8,2). (1)
Row 4 (4,7) -> Row 5 (6,7) -> Row 6 (7,3) -> Row 8 (3,9). (2)
How to query table like that :
LinkA linkB SameLink
-------------------------------
1 10 1
10 2 1
2 5 1
4 7 2
6 7 2
7 3 2
8 2 1
3 9 2
Test table :
create table Data(
linkA INT,
linkB INT );
insert into Data(linkA, linkB)
values ('1', '10'),('10', '2'),('2', '5'),('4', '7'),('6', '7'),('7', '3'),('8', '2'),('3', '9');
Following Query using CTE should solve your question, just set the parameter in the first line:
DECLARE #Start AS INT = 1;
WITH CTE
AS
(
-- Case Base
SELECT LinkA, LinkB
FROM Data E1
WHERE LinkA = #Start
UNION ALL
-- Recursive Branch
SELECT C.LinkA, E2.LinkB
FROM CTE C
INNER JOIN Data E2
ON C.LinkB = E2.LinkA
)
SELECT *
FROM CTE
ORDER BY LinkA, LinkB;
More details on Tips 4 DBs
I created a solution based on SQL cursor
I also documented the solution for grouping related data into data islands in SQL to provide more detail about the SQL script I share below
CREATE TABLE RelatedNodes (id int identity(1,1), nodes varchar(max))
DECLARE #LinkA Int
DECLARE #LinkB Int
DECLARE #cnt Int
DECLARE #Nodes1 varchar(max)
DECLARE #Nodes2 varchar(max)
DECLARE #Id1 Int
DECLARE #Id2 Int
DECLARE sqlcursor CURSOR FAST_FORWARD FOR
select
LinkA, LinkB
from Data
Order By LinkA, LinkB
OPEN sqlcursor
FETCH NEXT FROM sqlcursor INTO #LinkA, #LinkB
WHILE ##FETCH_STATUS = 0
BEGIN
---
select
Id
into ##tblId
from RelatedNodes
where
nodes like ('%,' + convert(varchar(max),#LinkA) + ',%') or
nodes like ('%,' + convert(varchar(max),#LinkB) + ',%')
select #cnt = count(*) from ##tblId
if #cnt = 0
begin
insert into RelatedNodes
select
case when #LinkA < #LinkB
then (',' + convert(varchar(max),#LinkA) + ',' + convert(varchar(max),#LinkB) + ',')
else (',' + convert(varchar(max),#LinkB) + ',' + convert(varchar(max),#LinkA) + ',')
end
end
else if #cnt = 1
begin
update RelatedNodes
set nodes = nodes + convert(varchar(max),#LinkA) + ',' + convert(varchar(max),#LinkB) + ','
from RelatedNodes rn
inner join ##tblId t
on rn.id = t.id
end
else if #cnt = 2
begin
select top 1
#Id1 = rn.Id,
#Nodes1 = nodes
from RelatedNodes rn
inner join ##tblId t
on rn.id = t.id
order by t.id
select top 1
#Id2 = rn.Id,
#Nodes2 = nodes
from RelatedNodes rn
inner join ##tblId t
on rn.id = t.id
order by t.id desc
set #Nodes1 = #Nodes1 + #Nodes2
update RelatedNodes
set nodes = #Nodes1
where Id = #Id1
delete RelatedNodes where Id = #Id2
end
drop table ##tblId
FETCH NEXT FROM sqlcursor INTO #LinkA, #LinkB
END
CLOSE sqlcursor
DEALLOCATE sqlcursor
select
LinkA, LinkB, GroupId
from Data
inner join (
select nodes, ROW_NUMBER() over (order by id) as GroupId from RelatedNodes
) g
on g.nodes like ('%,' + convert(varchar(max),LinkA) + ',%')
Order By GroupId, LinkA, LinkB
Outcome of the execution of above SQL script is as follows providing data for all rows of sample data

Right way to subtract in a stored procedure

I have the following query in my stored procedure
DECLARE #I INT
DECLARE #TenPercent int
DECLARE #RowsCount int
SET #TenPercent =10
SET #I = 1
SELECT
#I, dbo.tblVegetationType.VegTypeCode, dbo.tblVegetationType.VegTypeName
FROM
dbo.tblVegetationType
INNER JOIN
dbo.tblVegTypeVegFormationLink ON dbo.tblVegetationType.VegTypeID = dbo.tblVegTypeVegFormationLink.VegTypeID
INNER JOIN
tblCMAVegTypeLink ON dbo.tblVegetationType.VegTypeID = dbo.tblCMAVegTypeLink.VegTypeID
WHERE
dbo.tblVegetationType.PercentageCleared >= (#PercentCleared - #TenPercent)
AND dbo.tblVegTypeVegFormationLink.VegetationFormationID = #VegetationFormationID
AND dbo.tblCMAVegTypeLink.CMAID = #CMAID
I have following condition
dbo.tblVegetationType.PercentageCleared >= (#PercentCleared - #TenPercent)
What I am trying to do here: if PercentCleared is 60% then I want to query to pick the list from 50 %.
So I just add the SET #TenPercent = 10 and subtract from the condition.
Is that a right way to do?
Another way of writing the query can be:
SELECT #I,
VT.VegTypeCode,
VT.VegTypeName
FROM dbo.tblVegetationType VT
INNER JOIN dbo.tblVegTypeVegFormationLink VTVF
ON VT.VegTypeID = VTVF.VegTypeID
INNER JOIN tblCMAVegTypeLink CVT
ON VT.VegTypeID = CVT.VegTypeID
WHERE 1= case when #PercentCleared >= 60 and VT.PercentageCleared <= 50 then 1
-- you can add condition when #PercentCleared < 60 then what values of
-- VT.PercentageCleared are to be considered
when #PercentCleared < 60 and VT.PercentageCleared <= 50 then 1
end
AND VTVF.VegetationFormationID = #VegetationFormationID
AND CVT.CMAID = #CMAID

Sum of multiple values of one variable

I want to sum the variable that is holding the value in a loop,
Here's my table:
name | pkey | cinema1~cinema10 | total_QTy | total_sales
aaa | 1 | 100.00 ~ 200.00 | 2 | 300.00
bbb | 2 | 150.00 ~ 145.00 | 3 | 295.00
total_Qty is the sum of the tickets bought in cinema1~cinema10 for name aaa
and I don't know how to do this. I am only getting the last value of counted ticket which is in name bbb cinema10.
Help me please. I'm stuck here.
Here is my code for getting the amount and qty
WHILE ISNULL(#cinema_key, 0) <> 0
BEGIN
SET #amount = 0
SELECT #amount =(SUM(t1.price)), #qty = (count(t1.cnt))
FROM(
SELECT
(ISNULL(SUM(mctrs.price),0) - (ISNULL(SUM(mctrs.lgu_tax_amount),0) + ISNULL(SUM(mctrs.ordinance_1),0) + ISNULL(SUM(mctrs.ordinance_2),0)+ ISNULL(SUM(mctrs.ordinance_3),0) + ISNULL(SUM(mctrs.ordinance_4),0) )) AS 'price',
count(mctrs.[key]) as 'cnt', mctrs.[key] as ckey
FROM
movie_calendar mc
INNER JOIN
movie_database md
ON
mc.movie_key = md.[key] AND mc.screening_start_date = #tdate
INNER JOIN
cinemas c
ON
mc.cinema_key = c.[key] AND c.[key] = #cinema_key
INNER JOIN
movie_calendar_times mct
ON
mct.movie_calendar_key = mc.[key]
LEFT OUTER JOIN
movie_calendar_time_reserved_seats mctrs
ON
mctrs.movie_calendar_time_key = mct.[key]
INNER JOIN
patrons p
ON
mctrs.patron_key = p.[key]
WHERE mctrs.status = 1 AND mctrs.[committed]=1
GROUP BY p.patron_tag,mctrs.price,P.APPLY_LGU_TAX ,P.LGU_TAX_AMOUNT, mctrs.[key]
)t1
SET #buffer = 'UPDATE #temptable SET cinema'+CAST(#count AS VARCHAR)+' = '+CAST(ISNULL(sum(#amount),0) AS VARCHAR)+' WHERE [date] = '''+CAST (#tdate AS VARCHAR)+''''
PRINT (#buffer)
EXEC(#buffer)
insert into #tqty(qty) values(#qty)
DELETE FROM #cinema_list WHERE cinema_key = #cinema_key
SET #cinema_key = NULL
SET #cinema_code = NULL
SELECT TOP 1 #cinema_key = cinema_key, #cinema_code = cinema_code FROM #cinema_list ORDER BY display_order
SET #count = #count + 1
END /*WHILE CINEMA KEY*/
and here's my code in updating the total_Qty and total_sales:
WHILE #count < #cinema_count
BEGIN
SET #count = #count+1.
SET #select = #select+'cinema'+CAST(#count AS VARCHAR)+'+'
END
SET #select = SUBSTRING(#select, 1, LEN(#select) - 1)
SET #buffer = 'UPDATE #temptable SET total_quantity = ' +cast(#qty as varchar) + ', ' + 'total_sales = '+#select
PRINT #buffer
EXEC( #buffer)
Help please :3 Thanks :)
I agree with #Dave Collins that this isn't database design at its greatest however if you want the simple answer, you need to add the existing value to the running total in your update.
Change this:
SET #buffer = 'UPDATE #temptable SET cinema'+CAST(#count AS VARCHAR)+' = '+CAST(ISNULL(sum(#amount),0) AS VARCHAR)+' WHERE [date] = '''+CAST (#tdate AS VARCHAR)+''''
To this:
SET #buffer = 'UPDATE #temptable SET cinema'+CAST(#count AS VARCHAR)+' = ISNULL(cinema,0) + '+CAST(ISNULL(sum(#amount),0) AS VARCHAR)+' WHERE [date] = '''+CAST (#tdate AS VARCHAR)+''''

NULL value returned when using SUM function on two columns while populating table in SQL Server 2008

INSERT INTO table is producing a NULL value for the returned recordset. I'm trying to add the SUM(m.earnings + m.fpearn) from pfinancial table and userid & minpay from the userbase table.
What am I doing wrong? Also is there a better way to reiterate through the temp table of id's ?
From the tables below I should populate the publsher_monthly table with one unique id per userid, the minpay amount from the userbase and the sum of the m.earnings + m.fpearn columns from the pfinancial table
publisher_monthly table
pmuseris pmminpay pmearnings
5 20 75
6 30 27
userbase table
userid minpay
5 20
6 30
pfinancial table
userid earnings fpearn
5 10 30
5 20 15
6 15 12
My query:
DECLARE #realuserid bigint
CREATE TABLE #tmppmuserids(
idx bigint Primary Key IDENTITY(1,1),
tmppmuserid bigint NULL
)
INSERT INTO #tmppmuserids
SELECT DISTINCT userid FROM pfinancial
DECLARE #i bigint
DECLARE #numrows bigint
SET #i = 1
SET #numrows = (SELECT COUNT(*) FROM #tmppmuserids)
IF #numrows > 0
WHILE (#i <= (SELECT MAX(idx) FROM #tmppmuserids))
BEGIN
SET #realuserid = (SELECT tmppmuserid FROM #tmppmuserids WHERE idx = #i)
--PROBLEM HERE
INSERT INTO publisher_monthly (pmearnings, pmuserid, pmminpay)
SELECT
SUM(m.earnings + m.fpearn), MAX(#realuserid), MAX(u.minpay)
FROM pfinancial m
INNER JOIN userbase u on u.userid = m.userid
WHERE
m.userid = #realuserid AND
(m.created >= DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()),0)) AND
(m.created < DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) + 1, 0))
--END PROBLEM
SET #i = #i + 1
END
SELECT * FROM #tmppmuserids
SELECT * FROM publisher_monthly
DROP TABLE #tmppmuserids
Place an IsNull around them:
SELECT SUM(IsNull(m.earnings, 0) + IsNull(m.fpearn, 0))
or even around the whole thing:
SELECT IsNull(SUM(m.earnings + m.fpearn), 0)