How to set previous row's column value? - sql-server-2008

I use MS SQL Server 2008 R2.
Is it possible to set the value of BarCode column in row with StatusID = 3 to the same value in row with BarCode with StatusID = 10.

Try this:
DECLARE #t TABLE
(
StatusID INT ,
UserID INT ,
BarCode CHAR(10)
)
INSERT INTO #t
VALUES ( 1, 3378, '-1' ),
( 2, 3378, '-1' ),
( 10, 3378, 'some_code1' ),
( 1, 3379, '-1' ),
( 3, 3379, '-1' ),
( 10, 3379, 'some_code2' );
WITH cte
AS ( SELECT StatusID ,
UserID ,
BarCode ,
ROW_NUMBER() OVER ( PARTITION BY UserID ORDER BY StatusID ) AS rn
FROM #t
)
UPDATE c1
SET BarCode = c2.BarCode
FROM cte c1
JOIN cte c2 ON c1.UserID = c2.UserID
AND c1.rn + 1 = c2.rn
WHERE c2.StatusID = 10
AND c1.StatusID = 3
SELECT * FROM #t
Output:
StatusID UserID BarCode
1 3378 -1
2 3378 -1
10 3378 some_code1
1 3379 -1
3 3379 some_code2
10 3379 some_code2

Related

Sum the balance in history table

I need help I'm not able to achieve desired output. I have used cursor as shown below. I have two tables 1. Transaction 2. History. I need to sum the amount in Transaction table for ID and insert it in history table under revised_amount column and also store the amount before sum in Original_amount column. Below is the example. Thanks
Tran_ID ID Amount
1066 Dhan Group $4,800.00
1327 Dhan Group $2,670.00
1329 Dhan Group $1,800.00
1330 Dhan Group $1,290.00
3953 Admin Group 0
2650 Admin Group $364368.69
2651 Admin Group $1604546.97
Desired Output in history table
Hist_ID ID ORIGINAL_AMOUNT REVISED_AMOUNT
1 Dhan Group $4,800.00
2 Dhan Group $4,800.00 $7,470.00
3 Dhan Group $7,470.00 $9,270.00
4 Dhan Group $9,270.00 $10,560.00
5 Admin Group $0
6 Admin Group $0 $364,368.69
7 Admin Group $364,368.89 $1,968,915.86
=============================================================
USE [LEM]
BEGIN
DECLARE #Proj_RID nvarchar(255),
#Revised_Amount decimal(12,2),
#Original_Amount decimal(12,2)
DECLARE Running_Total CURSOR FOR
Select [ID], [Amount]
FROM [Transactions]
OPEN Running_Total;
FETCH NEXT FROM Running_Total into #Proj_RID, #Original_Amount;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Revised_Amount = #Revised_Amount+ #Original_Amount;
UPDATE HISTORY
SET REVISED_AMOUNT = #Revised_Amount,
Original_Amount = #Revised_Amount - #Original_Amount
WHERE [Project_ID] = #Proj_RID
FETCH NEXT FROM Running_Total into #Proj_RID, #Original_Amount;
END
CLOSE Running_Total;
DEALLOCATE Running_Total;
END
========================================================
Here is an example of how you can achieve this. Note that you need to use some ordering column as TransactionDate:
;WITH cte AS(SELECT *, (SELECT SUM(amount) FROM Transactions
WHERE id = t.ID AND TranDate < t.TranDate) AS ORIGINAL_AMOUNT
FROM Transactions t)
SELECT ID, ORIGINAL_AMOUNT, Amount + ISNULL(ORIGINAL_AMOUNT, 0) AS REVISED_AMOUNT
FROM cte
Here is complete script(but I use transaction ID as ordering column):
DECLARE #t TABLE
(
Tran_ID INT ,
ID NVARCHAR(100) ,
Amount MONEY
)
INSERT INTO #t
VALUES ( 1066, 'Dhan Group', 4800.00 ),
( 1327, 'Dhan Group', 2670.00 ),
( 1329, 'Dhan Group', 1800.00 ),
( 1330, 'Dhan Group', 1290.00 ),
( 2649, 'Admin Group', 0 ),
( 2650, 'Admin Group', 364368.69 ),
( 2651, 'Admin Group', 1604546.97 )
;WITH cte AS(SELECT *, (SELECT SUM(amount) FROM #t
WHERE id = t.ID AND Tran_ID < t.Tran_ID) AS ORIGINAL_AMOUNT
FROM #t t)
SELECT ID, ORIGINAL_AMOUNT, Amount + ISNULL(ORIGINAL_AMOUNT, 0) AS REVISED_AMOUNT
FROM cte
Output:
ID ORIGINAL_AMOUNT REVISED_AMOUNT
Dhan Group NULL 4800.00
Dhan Group 4800.00 7470.00
Dhan Group 7470.00 9270.00
Dhan Group 9270.00 10560.00
Admin Group NULL 0.00
Admin Group 0.00 364368.69
Admin Group 364368.69 1968915.66

how to sort row_number() in dynamic sql in sql server 2008

I have to create a Pivot from the below given sample table -
State Country
------------------------------
ALA Almaty Kazakhstan
AMD Ahmedabad India
AMM Amman Jordan
AMS Amsterdam Netherlands
ATH Athens Greece
AUH Abu Dhabi United Arab Emirates
BAH Manama Bahrain
I am doing this by dynamic sql as i want dynamic columns in pivot. My problem is that I am not able to sort values generated by ROW_NUMBER() in dynamic SQL. The variable #var1 in the below mentioned code is giving output as -
[1],[10],[11],[2],[3],[4],[5],[6],[7],[8],[9]
which is not in sorted order.
declare #myvar nvarchar(max)
declare #var1 nvarchar(max)
declare #new nvarchar(max)
set #var1 = (select stuff((select distinct '],[' + cast(ROW_NUMBER() over ( partition by country order by (select 1)) as varchar(100)) from sheet
for xml path('')),1,2,'') + ']')
select #var1
set #myvar =
'select * from
(select *,ROW_NUMBER() over (partition by country order by (select 1)) as rn
from sheet
)as abc
pivot
(
max([state]) for rn
in (' + #var1 + ')
) as pvt'
set #new = 'select * into ##a from (' + #myvar + ') as t'
exec sp_executesql #new
You can try this:
WITH cte
AS ( SELECT ROW_NUMBER() OVER ( PARTITION BY country ORDER BY ( SELECT 1 ) ) rn
FROM sheet
)
SELECT #var1 = STUFF(( SELECT '],[' + CAST(rn AS NVARCHAR(MAX))
FROM cte
GROUP BY rn
ORDER BY rn
FOR XML PATH('') ), 1, 2, '') + ']'
SELECT #var1
For test data it works:
DECLARE #t TABLE ( i INT )
DECLARE #var1 NVARCHAR(MAX)
INSERT INTO #t
VALUES ( 1 ),
( 1 ),
( 2 ),
( 2 ),
( 2 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 3 ),
( 4 ),
( 4 );
WITH cte
AS ( SELECT ROW_NUMBER() OVER ( PARTITION BY i ORDER BY ( SELECT 1 ) ) rn
FROM #t
)
SELECT #var1 = STUFF(( SELECT '],[' + CAST(rn AS NVARCHAR(MAX))
FROM cte
GROUP BY rn
ORDER BY rn
FOR XML PATH('') ), 1, 2, '') + ']'
SELECT #var1
Output:
[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11]

How to get rid of repeated rows?

This is the tables structure I have:
1) When I use this query:
SELECT T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.StatusID
--,case when (dbo.T_ActionTicketLog.StatusID <> 2 and dbo.T_ActionTicketLog.StatusID <> 6) then dbo.T_TicketPrint.TicketBarCode
--else null end as TicketBarCode
FROM T_ActionTicketLog
LEFT OUTER JOIN T_OrderTicket ON T_ActionTicketLog.TicketOrderID = T_OrderTicket.ID
--LEFT OUTER JOIN T_TicketPrint ON T_OrderTicket.ActionTicketID = T_TicketPrint.ActionTicketID and T_OrderTicket.ID = T_TicketPrint.OrderTicketID
where T_ActionTicketLog.ActionTicketID = 24014999
Everything works fine and looks as following:
2) But, when I use this query because I need T_TicketPrint.TicketBarCode:
SELECT T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.StatusID
,case when (dbo.T_ActionTicketLog.StatusID <> 2 and dbo.T_ActionTicketLog.StatusID <> 6) then dbo.T_TicketPrint.TicketBarCode
else null end as TicketBarCode
FROM T_ActionTicketLog
LEFT OUTER JOIN T_OrderTicket ON T_ActionTicketLog.TicketOrderID = T_OrderTicket.ID
LEFT OUTER JOIN T_TicketPrint ON T_OrderTicket.ActionTicketID = T_TicketPrint.ActionTicketID and T_OrderTicket.ID = T_TicketPrint.OrderTicketID
where T_ActionTicketLog.ActionTicketID = 24014999
I've got the extra rows and it looks as following:
Here we have the sold tickets in T_TicketPrint table. When the ticket is sold (status 3) it can be printed out (status 10). The important thing is when we print the ticket, every time new bar code is generated. In this case we have a ticket that was sold and printed out 3 times with 3 different bar codes.
The desired result (other values in TicketBarCode column should be NULL):
How to get rid of extra rows?
This is final correct script:
;WITH cte1
AS (SELECT T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.TicketOrderID, T_ActionTicketLog.StatusID, T_ActionTicketLog.Created,
CASE WHEN StatusID IN (3, 10) THEN 1
ELSE 0
END
* ROW_NUMBER() OVER ( PARTITION BY T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.StatusID ORDER BY T_ActionTicketLog.Created ) AS rn
FROM T_ActionTicketLog
LEFT OUTER JOIN T_OrderTicket ON T_ActionTicketLog.TicketOrderID = T_OrderTicket.ID
),
cte2
AS ( SELECT ActionTicketID , OrderTicketID, TicketBarCode,
ROW_NUMBER() OVER ( PARTITION BY ActionTicketID ORDER BY Created ) AS rn
FROM T_TicketPrint
)
SELECT c1.ActionTicketID, c1.StatusID , oa.TicketBarCode
FROM cte1 c1
OUTER APPLY ( SELECT *
FROM cte2 c2
WHERE c1.ActionTicketID = c2.ActionTicketID AND c1.TicketOrderID = c2.OrderTicketID AND c1.rn = c2.rn
) oa
where c1.ActionTicketID = 24014999
order by c1.Created
If I got you right you need to apply to first pair of(3, 10) the first barcode, second barcode to second pair and so on. But it is not clear which of these pairs is first or second.
This is test script:
DECLARE #actions TABLE
(
TicketID INT ,
StatusID INT
)
DECLARE #prints TABLE
(
TicketID INT ,
BarCode NVARCHAR(MAX)
)
INSERT INTO #actions
VALUES ( 1, 2 ),
( 1, 4 ),
( 1, 3 ),
( 1, 10 ),
( 1, 6 ),
( 1, 3 ),
( 1, 10 ),
( 1, 6 ),
( 1, 3 ),
( 1, 10 ),
( 1, 6 ),
( 1, 7 )
INSERT INTO #prints
VALUES ( 1, 'C1' ),
( 1, 'C2' ),
( 1, 'C3' );
WITH cte1
AS ( SELECT * ,
CASE WHEN StatusID IN ( 3, 10 ) THEN 1
ELSE 0
END
* ROW_NUMBER() OVER ( PARTITION BY TicketID, StatusID ORDER BY StatusID ) AS rn
FROM #actions a
),
cte2
AS ( SELECT * ,
ROW_NUMBER() OVER ( PARTITION BY TicketID ORDER BY BarCode ) AS rn
FROM #prints a
)
SELECT c1.TicketID ,
c1.StatusID ,
oa.BarCode
FROM cte1 c1
OUTER APPLY ( SELECT *
FROM cte2 c2
WHERE c1.TicketID = c2.TicketID
AND c1.rn = c2.rn
) oa
Ouptut:
TicketID StatusID BarCode
1 2 NULL
1 3 C1
1 3 C2
1 3 C3
1 4 NULL
1 6 NULL
1 6 NULL
1 6 NULL
1 7 NULL
1 10 C1
1 10 C2
1 10 C3
Something like:
;WITH cte1
AS ( SELECT T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.OrderTicketID, T_ActionTicketLog.StatusID ,
CASE WHEN StatusID IN ( 3, 10 ) THEN 1
ELSE 0
END
* ROW_NUMBER() OVER ( PARTITION BY T_ActionTicketLog.ActionTicketID, T_ActionTicketLog.StatusID ORDER BY T_ActionTicketLog.Created ) AS rn
FROM T_ActionTicketLog
LEFT OUTER JOIN T_OrderTicket ON T_ActionTicketLog.TicketOrderID = T_OrderTicket.ID
),
cte2
AS ( SELECT ActionTicketID , OrderTicketID, TicketBarCode
ROW_NUMBER() OVER ( PARTITION BY ActionTicketID ORDER BY Created ) AS rn
FROM T_TicketPrint
)
SELECT c1.ActionTicketID, c1.StatusID , oa.TicketBarCode
FROM cte1 c1
OUTER APPLY ( SELECT *
FROM cte2 c2
WHERE c1.ActionTicketID = c2.ActionTicketID AND c1.ID = c2.OrderTicketID AND c1.rn = c2.rn
) oa

Selecting data from multiple rows from a temporary table create by SELECT

I have the following SQL query which is somehow broken:
SELECT *
FROM (
SELECT ID, TEST, CHR, NUMBER
FROM Test_Table
JOIN ...
WHERE ...
) TEMP_TABLE
FROM TEMP_TABLE a
LEFT
JOIN TEMP_TABLE b
ON b.test = a.test
AND b.chr = 'x'
WHERE a.number IN (5,6)
AND b.id IS NULL
GROUP
BY a.test
HAVING COUNT(*) = 2;
From the first FROM statement I get the following temporary table:
ID , TEST, CHR , NUMBER
------------------------------
( 1 , 7 , 'C' , 5),
( 2 , 7 , 'T' , 6),
( 3 , 8 , 'C' , 4),
( 4 , 8 , 'T' , 5),
( 5 , 9 , 'A' , 4),
( 6 , 9 , 'G' , 5),
( 7 , 10 , 'T' , 4),
( 8 , 10 , 'A' , 5),
( 9 , 10 , 'X' , 6),
(10 , 14 , 'T' , 4),
(11 , 14 , 'G' , 5);
From FROM TEMP_TABLE ... I try to implement the following conditions:
For example test column 7 contains two rows, if the number column contains values 5 AND 6, AND the value is NOT X in the chr column, I would like to select select the rows with 7 in the test column.
For example test column 10 contains three rows, if the number column contains values 5 AND 6, AND the value X exists in the chr column, I would like to exclude rows with 10 in the test column.
As result it should only be test column with 7, because test column 7 have 5 and 6 in the number column and not X.
Result example:
ID | TEST | CHR | NUMBER
1 | 7 | C | 5
2 | 7 | T | 6
What did go wrong with the above SQL query?
Your query has two FROM clauses remove one and try like below
SELECT *
FROM (
SELECT ID, TEST, CHR, NUMBER
FROM Test_Table
JOIN ...
WHERE ...
) a
LEFT JOIN
(
SELECT ID, TEST, CHR, NUMBER
FROM Test_Table
JOIN ...
WHERE ...
) b
ON b.test = a.test
AND b.chr = 'x'
WHERE a.number IN (5,6)
AND b.id IS NULL
GROUP
BY a.test
HAVING COUNT(*) = 2;
A easier way to do this is to create a TEMPORARY table using TEMPORARY keyword like mentioned here
CREATE TEMPORARY TABLE TEMP_TABLE (ID int, TEST varchar(100), CHR char, NUMBER int );
INSERT INTO TEMP_TABLE
(SELECT ID, TEST, CHR, NUMBER
FROM Test_Table
JOIN ...
WHERE ...);
SELECT *
FROM TEMP_TABLE a
LEFT
JOIN TEMP_TABLE b
ON b.test = a.test
AND b.chr = 'x'
WHERE a.number IN (5,6)
AND b.id IS NULL
GROUP
BY a.test
HAVING COUNT(*) = 2;

creating sql query for selecting multiple data

i need a sql query for my table tbl1
sample contents of the table like this
serial ida idb
1 1 2
2 1 3
3 3 7
4 3 6
5 2 4
6 2 6
.
in the table tbl1 column ida and idb are related like 1 is related with 2 and 3 , 2 is related with 4 and 6
ida value 1 s related data is 2 and 3 and i want to select the related data of 1' s related data (2 and 3).
2 and 3 s related data is 7, 6 and 4, 6. so the output will be (7,6,4)
. i need a sql query to display this out put. can anyone share some idea how to do that ..
SELECT DISTINCT idb FROM tbl1 WHERE ida = 2 OR ida = 3;
Is this what you were looking for?
EDIT: Corrected determining child branches of the hierarchy.
This may be of some use:
-- Sample data.
declare #Table as table ( serial int identity, ida int, idb int )
insert into #Table ( ida, idb ) values
( 1, 2 ), ( 1, 3 ),
( 3, 7 ), ( 3, 6 ),
( 2, 4 ), ( 2, 6 )
select * from #Table
-- Demonstrate recursive query.
; with CTE as (
-- Start with ida = 1.
select serial, ida, idb, 1 as depth, path = cast( right( '000000' + cast( ida as varchar(6) ), 6 ) as varchar(1024) )
from #Table
where ida = 1
union all
-- Add each row related to the most recent selected row(s).
select T.serial, T.ida, T.idb, C.depth + 1, cast( C.path + right( '000000' + cast( T.ida as varchar(6) ), 6 ) as varchar(1024) )
from CTE as C inner join
#Table as T on T.ida = C.idb
)
-- Show everything.
select *
from CTE
-- Repeat the recursive query.
; with CTE as (
-- Start with ida = 1.
select serial, ida, idb, 1 as depth, path = cast( right( '000000' + cast( ida as varchar(6) ), 6 ) as varchar(1024) )
from #Table
where ida = 1
union all
-- Add each row related to the most recent selected row(s).
select T.serial, T.ida, T.idb, C.depth + 1, cast( C.path + right( '000000' + cast( T.ida as varchar(6) ), 6 ) as varchar(1024) )
from CTE as C inner join
#Table as T on T.ida = C.idb
)
-- Select only the deepest children.
select distinct idb
from CTE as C
where not exists ( select 42 from CTE where left( path, len( C.path ) ) = C.path and len( path ) > len( C.path ))
order by idb
Left as an exercise is pivoting the result.
select distinct idb from tbl1 where ida in (select idb from tbl1 where ida = 1)