export and import inventory warehouse in a table - sql-server

I have a table with 4 column in sql (key ID):
ID Items Import Export
1 A1 1333 0
2 A1 0 368
3 A1 0 252
4 A1 1965 0
5 A1 0 162
6 A1 0 551
7 A1 0 69
I want calculate inventory ware in a row.But not the results as expected.
You can help me get the results as below? With column Inventory
ID Items Import Export Inventory
1 A1 1333 0 1333
2 A1 0 368 965
3 A1 0 252 713
4 A1 1965 0 2678
5 A1 0 162 2516
6 A1 0 551 1965
7 A1 0 69 1896
This is my code:
Select ID,
(A.Invent + Import-Sum(Export)) as Inventory
From MyColumn,
(
Select Top 1 (Import - Export) as Invent
From MyColumn
Where Items in ('A1')
) as A
Where Items in ('A1')
Group by
A.Invent,
Import,ID

Being 2008 you're missing the sum() over, however there is another option
Example
Declare #YourTable Table ([ID] int,[Items] varchar(50),[Import] int,[Export] int)
Insert Into #YourTable Values
(1,'A1',1333,0)
,(2,'A1',0,368)
,(3,'A1',0,252)
,(4,'A1',1965,0)
,(5,'A1',0,162)
,(6,'A1',0,551)
,(7,'A1',0,69)
Select A.*
,B.*
from #YourTable A
Cross Apply (
Select Inventory = sum(Import-Export)
From #YourTable
Where Items=A.Items and ID<=A.ID
) B
Returns
ID Items Import Export Inventory
1 A1 1333 0 1333
2 A1 0 368 965
3 A1 0 252 713
4 A1 1965 0 2678
5 A1 0 162 2516
6 A1 0 551 1965
7 A1 0 69 1896

Using a join
Also window function but this is not available in 2008
declare #T table (id int identity primary key, import int, export int);
insert into #T (import, export) values
(1333, 0)
, (0, 368)
, (0, 252)
, (1965, 0)
, (0, 162)
, (0, 551)
, (0 , 69);
select t1.id, t1.import, t1.export
, sum(t2.import - t2.export) AS inven
from #T t1
join #T t2
on t2.id <= t1.id
group by t1.id, t1.import, t1.export
order by t1.id
select *
, sum(import - export) over (order by t.id) as inven
from #T t;
id import export inven
----------- ----------- ----------- -----------
1 1333 0 1333
2 0 368 965
3 0 252 713
4 1965 0 2678
5 0 162 2516
6 0 551 1965
7 0 69 1896

Related

How to Sort Amount Number Negative and Positive Number In SQL server

I have working SQL Server.I have More than 20000 Lines Using SQL server.I have column Filed Name Amount. in Amount Filed Inserted negative and Positive Number .Now I want Sort Amount Field Negative and Positive Number
Example Like :
Entity ExpenseTypeCode ExpenseType Amount
11 043 Hotel 5
12 044 travel 23
13 045 drink 55
14 046 Dinner 23
15 047 airline 556
16 048 Hotel -5
I how Like More than 30000 LINES .IN my table i have Expense type but negative and Positive value
I want Sort My table Like negative and Positive order same value
Entity ExpenseTypeCode ExpenseType Amount
11 043 Hotel 5
16 048 Hotel -5 --> Want sort like this
12 044 travel 23
13 045 drink 55
14 046 Dinner 23
15 047 airline 556
How can i sort my table liKE ?
Use ABS Function in sorting:
ABS() : It will convert your negative value to positive
SELECT
*
FROM TableName
Order BY ABS(Amount)
If you wants if negative and positive value same and order should consider positive first then:
SELECT
*
FROM TableName
Order BY ABS(Amount),Amount*-1
Example:
Initial
Output
select * from #t t
order by expensetype,
case when amount > 0 then 1 else 2 end
result
Entity ExpenseTypeCode ExpenseType Amount
----------- --------------- ----------- -----------
15 47 airline 556
14 46 Dinner 23
13 45 drink 55
11 43 Hotel 5
16 48 Hotel -5
12 44 travel 23
If you are looking for matching pairs then something like this might be what you want
declare #t table(Entity int, ExpenseTypeCode int, ExpenseType varchar(10), Amount int)
insert into #t values
( 11, 043, 'Hotel' , 6),
( 8, 043, 'Hotel' , 5),
( 9, 043, 'Hotel' , 5),
( 10, 043, 'Hotel' , 5),
( 12, 044, 'travel' , 23),
( 13, 045, 'drink' , 55),
( 14, 046, 'Dinner' , 23),
( 15, 047, 'airline' , 556),
( 16, 048, 'Hotel' , -5),
( 17, 048, 'Hotel' , -5),
( 18, 043, 'Hotel' , -6),
( 19, 043, 'Hotel' , -6)
select t.*,row_number() over(partition by t.ExpenseType, t.amount order by t.entity) rn,t.amount as absamount
from #t t
where t.amount > 0
union all
select t.*,row_number() over(partition by t.ExpenseTypeCode, t.amount order by t.entity) rn, abs(t.amount)
from #t t
where t.amount < 0
order by t.expensetype,absamount,rn,t.amount desc
result
Entity ExpenseTypeCode ExpenseType Amount rn absamount
----------- --------------- ----------- ----------- -------------------- -----------
15 47 airline 556 1 556
14 46 Dinner 23 1 23
13 45 drink 55 1 55
8 43 Hotel 5 1 5
16 48 Hotel -5 1 5
9 43 Hotel 5 2 5
17 48 Hotel -5 2 5
10 43 Hotel 5 3 5
11 43 Hotel 6 1 6
18 43 Hotel -6 1 6
19 43 Hotel -6 2 6
12 44 travel 23 1 23
or possibly a full join
select s.*,t.* from
(
select t.*,row_number() over(partition by t.ExpenseType, t.amount order by t.entity) rn
from #t t
where t.amount > 0
) s
full join
(
select t.*,row_number() over(partition by t.ExpenseTypeCode, t.amount order by t.entity) rn
from #t t
where t.amount < 0
) t on t.expensetype = s.expensetype and t.rn = s.rn and abs(t.amount) = s.amount
order by s.expensetype
Entity ExpenseTypeCode ExpenseType Amount rn Entity ExpenseTypeCode ExpenseType Amount rn
----------- --------------- ----------- ----------- -------------------- ----------- --------------- ----------- ----------- --------------------
NULL NULL NULL NULL NULL 19 43 Hotel -6 2
15 47 airline 556 1 NULL NULL NULL NULL NULL
14 46 Dinner 23 1 NULL NULL NULL NULL NULL
13 45 drink 55 1 NULL NULL NULL NULL NULL
11 43 Hotel 6 1 18 43 Hotel -6 1
10 43 Hotel 5 3 NULL NULL NULL NULL NULL
8 43 Hotel 5 1 16 48 Hotel -5 1
9 43 Hotel 5 2 17 48 Hotel -5 2
12 44 travel 23 1 NULL NULL NULL NULL NULL

Query is very slow

I have tables
table1
epid etid id EValue reqdate
----------- ----------- ----------- ------------ ----------
15 1 1 498925307069 2012-01-01
185 1 2 A5973FC43CE3 2012-04-04
186 1 2 44C6A4B776A2 2012-04-05
205 1 2 7A0ED3F1DA13 2012-09-19
206 1 2 77771D65F9C4 2012-09-19
207 1 2 AD74A4AA41BD 2012-09-19
208 1 2 9595ABE5A0C8 2012-09-19
209 1 2 7611D2FB395B 2012-09-19
210 1 2 04A510D6067A 2012-09-19
211 1 2 24D43EC268F8 2012-09-19
table2
PEId Id EPId
----------- ----------- -----------
43 9 15
44 10 15
45 11 15
46 12 15
47 13 15
48 14 15
49 15 15
50 16 15
51 17 15
52 18 15
table3
PLId PEId Id ToPayId
----------- ----------- ----------- -----------
71 43 9 1
72 43 9 2
73 44 10 1
74 44 10 2
75 45 11 1
76 45 11 2
77 46 12 1
78 46 12 2
79 47 13 1
80 47 13 2
I want to get one id whose count is less than 8 in table 3 and order by peid in table 2,
I have written query
SELECT Top 1 ToPayId FROM
(
SELECT Count(pl.ToPayId) C, pl.ToPayId
FROM table3 pl
INNER JOIN table2 pe ON pl.peid = pe.peid
INNER JOIN table1 e ON pe.epid = e.epid
WHERE e.EtId=1 GROUP BY pl.ToPayId
) As T
INNER JOIN table2 p ON T.ToPayId= p.Id
WHERE C < 8 ORDER BY p.PEId ASC
This query executes more than 1000 times in stored procedure depends on the entries in user-defined-table-type using while condition.
But it is very slow as we have millions of entries in each table.
Can anyone suggest better query regarding above?
maybe try with the having clause to get rid of the from select
select table2.id as due
from table3 inner join table2 on table2.PEId=table3.PEId...
group by ...
having count(due) <8
order by ...
-> you have a redundant Id column in table3 : seems pretty useless as the couple PEId and Id appears unique so remove it and reduce the size of table 3 by 25% hence improving performance of db
Will.. since you did not provide enough sample data and I am not sure what exactly your business logic is. So that I can just modify the code in blind.
SELECT ToPayId
FROM (
SELECT TOP 1 Count(pl.ToPayId) C, pl.ToPayId, pe.PEId
FROM table3 as pl
INNER JOIN table2 as pe ON pl.peid = pe.peid AND pl.ToPayId = pe.Id
INNER JOIN table1 e ON pe.epid = e.epid
WHERE e.EtId=1
GROUP BY pl.ToPayId, pe.PEId
HAVING Count(pl.ToPayId) < 8
ORDER BY pe.PEId ASC
) AS T

Recursive function with sum of count of each child SQL Server 2005

I'm new here, so please accept my apologize if there is a rule that I ignored it.
I use SQL Server 2005.
I have a table which contains a parent-child structured tree.
There is a query that scans above mentioned tree. There is also another tree including some of children of the 1st table. Each child of 1st table could be repeated for more than 1 time in the 2nd table.
1st table (called TBL1):
CID Parent_ID Seq_NO CName
650 NULL 1 A
135 650 1 B
950 135 1 C
124 135 2 D
725 135 3 E
421 135 4 F
632 421 1 G
906 421 2 H
119 421 3 I
215 650 2 J
436 215 1 K
150 215 2 L
260 150 1 M
501 260 1 N
154 260 2 O
132 260 3 P
721 150 2 Q
960 215 3 R
Query for scannning the tree of TBL1
WITH SCAN_TREE(IID, QName, Parent_ID, levleTREE, HRName, SO) AS
(
SELECT
CID, CName, Parent_ID,
0 AS initlvl,
CAST(INIT_POINT.CName AS VARCHAR(MAX)) AS initName,
CAST(INIT_POINT.Seq_NO AS VARBINARY(MAX)) AS initSO
FROM TBL1 AS INIT_POINT
WHERE (INIT_POINT.CID=650)
UNION ALL
SELECT
LOOP_Q.CID, LOOP_Q.CName, LOOP_Q.Parent_ID,
FINAL_Q.levleTREE + 1 AS looplvl,
CAST(FINAL_Q.HRName + '-' + LOOP_Q.CName AS VARCHAR(MAX)) AS loopName,
CAST(FINAL_Q.SO + CAST(LOOP_Q.Seq_NO AS BINARY(4)) AS VARBINARY(MAX)) AS loopSO
FROM TBL1 AS LOOP_Q
INNER JOIN SCAN_TREE AS FINAL_Q ON LOOP_Q.Parent_ID = FINAL_Q.IID
)
SELECT
LAST_Q.IID, LAST_Q.QName, LAST_Q.Parent_ID, LAST_Q.levleTREE, LAST_Q.HRName
FROM SCAN_TREE AS LAST_Q
ORDER BY SO
The output of above query:*
IID QName Parent_ID levleTREE HRName
650 A NULL 0 A
135 B 650 1 A-B
950 C 135 2 A-B-C
124 D 135 2 A-B-D
725 E 135 2 A-B-E
421 F 135 2 A-B-F
632 G 421 3 A-B-F-G
906 H 421 3 A-B-F-H
119 I 421 3 A-B-F-I
215 J 650 1 A-J
436 K 215 2 A-J-K
150 L 215 2 A-J-L
260 M 150 3 A-J-L-M
501 N 260 4 A-J-L-M-N
154 O 260 4 A-J-L-M-O
132 P 260 4 A-J-L-M-P
721 Q 150 3 A-J-L-Q
960 R 215 2 A-J-R
2nd table (called TBL2):
MID
----
950
124
124
632v
632
632
421
What I want is the sum of all occurance of each child of 1nd table in 2nd table for each parent of 1st table.
I need a query to retrieve below result, actually I need first column (MID):
MID IID QName Parent_ID levleTREE HRName
7 650 A NULL 0 A
7 135 B 650 1 A-B
1 950 C 135 2 A-B-C
2 124 D 135 2 A-B-D
0 725 E 135 2 A-B-E
4 421 F 135 2 A-B-F
3 632 G 421 3 A-B-F-G
0 906 H 421 3 A-B-F-H
0 119 I 421 3 A-B-F-I
0 215 J 650 1 A-J
0 436 K 215 2 A-J-K
0 150 L 215 2 A-J-L
0 260 M 150 3 A-J-L-M
0 501 N 260 4 A-J-L-M-N
0 154 O 260 4 A-J-L-M-O
0 132 P 260 4 A-J-L-M-P
0 721 Q 150 3 A-J-L-Q
0 960 R 215 2 A-J-R
Thank you in advance.
You can do a few standard left joins here:
WITH SCAN_TREE(IID, QName, Parent_ID, levleTREE, HRName, SO, MID) AS
(
SELECT
CID,
CName,
Parent_ID,
0 AS initlvl,
CAST(INIT_POINT.CName AS VARCHAR(MAX)) AS initName,
CAST(INIT_POINT.Seq_NO AS VARBINARY(MAX)) AS initSO,
COUNT(T2.MID) as MID
FROM
TBL1 AS INIT_POINT
LEFT JOIN TBL2 AS T2 ON
INIT_POINT.CID = T2.MID
WHERE
INIT_POINT.CID=650
GROUP BY
CID,
CName,
ParentId,
Seq_NO
UNION ALL
SELECT
LOOP_Q.CID,
LOOP_Q.CName,
LOOP_Q.Parent_ID,
FINAL_Q.levleTREE + 1 AS looplvl,
CAST(FINAL_Q.HRName + '-' + LOOP_Q.CName AS VARCHAR(MAX)) AS loopName,
CAST(FINAL_Q.SO + CAST(LOOP_Q.Seq_NO AS BINARY(4)) AS VARBINARY(MAX)) AS loopSO,
COUNT(T2.MID) as MID
FROM
TBL1 AS LOOP_Q
INNER JOIN SCAN_TREE AS FINAL_Q ON
LOOP_Q.Parent_ID = FINAL_Q.IID
LEFT JOIN TBL2 AS T2 ON
LOOP_Q.CID = T2.MID
GROUP BY
LOOP_Q.CID,
LOOP_Q.CName,
LOOP_Q.Parent_ID,
FINAL_Q.levleTREE,
FINAL_Q.HRName,
FINAL_Q.SO,
FINAL_Q.Seq_NO
)
SELECT
LAST_Q.IID,
LAST_Q.QName,
LAST_Q.Parent_ID,
LAST_Q.levleTREE,
LAST_Q.HRName,
SUM(T2.MID) as MID
FROM
SCAN_TREE AS LAST_Q
LEFT JOIN SCAN_TREE as CHILDREN ON
CHILDREN.HRName like LAST_Q.HRName + '%'
GROUP BY
LAST_Q.IID,
LAST_Q.QName,
LAST_Q.Parent_ID,
LAST_Q.levleTREE,
LAST_Q.HRName
order by SO
All we're doing is joining TBL2 to TBL1 based on when the CID column equals the MID column. Then, we're counting the number of results we get. Since a left join will give us a null value for the MID column if one doesn't exist, we can rely on this for counting--null equals 0 to count. Next, outside of the CTE, we just join the CTE to itself and sum up those counts where the HRName (a nice hierarchy) begins with the given HRName, so A-B-C will grab the MID of A-B-C, A-B-C-D, A-B-C-D-E, and A-B-C-J, for example.

TSQL: non-boolean type specified error using update in a trigger

I'm trying to use the update function in T-sql in a trigger to check if a column has been changed or not. This is what I'm doing:
declare column_name cursor for select name from sys.columns where object_id = object_id(N'tblKit')
open column_name
fetch column_name into #colname
while (##Fetch_status=0)
begin
if(Update(#colname))
I get an error saying non-boolean type specified where a condition is expected. This is the syntax used in the msdn forum. So is there anything wrong with this?
I'm using Microsoft SQL server 2008 with Management Studio
If you simply want to log changes of individual columns in your trigger, you could try unpivoting, possibly in conjunction with full join. The idea is, you unpivot both inserted and deleted then join them on the table's key and the column containing the unpivoted names, filtering out the rows where the values are same.
Here's an example illustration of the method.
First, the table definitions:
CREATE TABLE TestTable (
ID int IDENTITY PRIMARY KEY,
Attr1 int,
Attr2 int,
Attr3 int
);
CREATE TABLE TestTableLog (
ID int IDENTITY PRIMARY KEY,
TableID int,
AttrName sysname,
OldValue int,
NewValue int,
Timestamp datetime DEFAULT GETDATE()
);
Next, a trigger for logging changes. This one will catch all the operations: insert, update, and delete:
CREATE TRIGGER trTestTable ON TestTable
AFTER INSERT, UPDATE, DELETE
AS BEGIN
WITH inserted_unpivot AS (
SELECT
ID,
AttrName,
Value
FROM inserted i
UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
),
deleted_unpivot AS (
SELECT
ID,
AttrName,
Value
FROM deleted d
UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
)
INSERT INTO TestTableLog (TableID, AttrName, OldValue, NewValue)
SELECT
ISNULL(i.ID, d.ID),
ISNULL(i.AttrName, d.AttrName),
d.Value,
i.Value
FROM inserted_unpivot i
FULL JOIN deleted_unpivot d
ON i.ID = d.ID AND i.AttrName = d.AttrName
WHERE CASE i.Value WHEN d.Value THEN 0 ELSE 1 END = 1
END
Now let's fill the TestTable with some data:
WHILE (SELECT COUNT(*) FROM TestTable) < 15
INSERT INTO TestTable
SELECT RAND() * 1000, RAND() * 1000, RAND() * 1000
;
Here's its contents before the subsequent changes:
ID Attr1 Attr2 Attr3
----------- ----------- ----------- -----------
1 820 338 831
2 795 881 453
3 228 430 719
4 36 236 105
5 246 115 649
6 488 657 438
7 990 360 15
8 668 978 724
9 872 385 562
10 460 396 462
11 62 599 630
12 145 815 439
13 595 7 54
14 587 85 655
15 80 606 407
And now let's perform some modifications to the contents:
UPDATE TestTable SET Attr2 = 35 WHERE ID = 3;
UPDATE TestTable SET Attr3 = 0 WHERE ID BETWEEN 6 AND 10;
INSERT INTO TestTable VALUES (1, 1, 1);
DELETE FROM TestTable WHERE ID = 14;
Here's what we've got in TestTable afterwards:
ID Attr1 Attr2 Attr3
----------- ----------- ----------- -----------
1 820 338 831
2 795 881 453
3 228 35 719
4 36 236 105
5 246 115 649
6 488 657 0
7 990 360 0
8 668 978 0
9 872 385 0
10 460 396 0
11 62 599 630
12 145 815 439
13 595 7 54
15 80 606 407
16 1 1 1
And this is what has been logged:
ID TableID AttrName OldValue NewValue Timestamp
----------- ----------- ----------- ----------- ----------- -----------------------
1 3 Attr2 430 35 2011-08-22 20:12:19.217
2 10 Attr3 462 0 2011-08-22 20:12:19.227
3 9 Attr3 562 0 2011-08-22 20:12:19.227
4 8 Attr3 724 0 2011-08-22 20:12:19.227
5 7 Attr3 15 0 2011-08-22 20:12:19.227
6 6 Attr3 438 0 2011-08-22 20:12:19.227
7 16 Attr1 NULL 1 2011-08-22 20:12:19.227
8 16 Attr3 NULL 1 2011-08-22 20:12:19.227
9 16 Attr2 NULL 1 2011-08-22 20:12:19.227
10 14 Attr1 587 NULL 2011-08-22 20:12:19.230
11 14 Attr2 85 NULL 2011-08-22 20:12:19.230
12 14 Attr3 655 NULL 2011-08-22 20:12:19.230
The setup, of course, has been somewhat simplified. In particular, all the main table's columns that are to be logged are of the same type, and so there's no need to convert data to some generic type to embrace various kinds of data. But maybe that's just what you need. And if not, I believe this can provide a good start to implementing the ultimate solution.

joining two tables [duplicate]

This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
How to join two tables
table 1
Date StartingAum
07/01/2010 120
08/01/2010 220
09/01/2010 320
table 2
Date DepContr withdra
01/01/2010 60 15
02/01/2010 70 25
03/01/2010 80 15
04/01/2010 30 89
05/01/2010 40 15
06/01/2010 25 85
07/01/2010 16 17
08/01/2010 19 21
09/01/2010 68 79
the output should be
Date StartingAum DepContr withdra
01/01/2010 0 60 15
02/01/2010 0 70 25
03/01/2010 0 80 15
04/01/2010 0 30 89
05/01/2010 0 40 15
06/01/2010 0 25 85
07/01/2010 120 16 17
08/01/2010 220 19 21
09/01/2010 320 68 79
i need the output exactly similar to that
DECLARE #Table1 table ([date] datetime, StartingAum int)
DECLARE #Table2 table ([date] datetime, DepContr int, withdra int)
INSERT #Table1 VALUES ('07/01/2010', 120)
INSERT #Table1 VALUES ('08/01/2010', 220)
INSERT #Table1 VALUES ('09/01/2010', 320)
INSERT #Table2 VALUES ('01/01/2010', 60 , 15)
INSERT #Table2 VALUES ('02/01/2010', 70 , 25)
INSERT #Table2 VALUES ('03/01/2010', 80 , 15)
INSERT #Table2 VALUES ('04/01/2010', 30 , 89)
INSERT #Table2 VALUES ('05/01/2010', 40 , 15)
INSERT #Table2 VALUES ('06/01/2010', 25 , 85)
INSERT #Table2 VALUES ('07/01/2010', 16 , 17)
INSERT #Table2 VALUES ('08/01/2010', 19 , 21)
INSERT #Table2 VALUES ('09/01/2010', 68 , 79)
SELECT
t2.[Date]
,ISNULL(t1.StartingAum, 0) AS StartingAum
,t2.DepContr
,t2.withdra
FROM #Table2 t2
LEFT JOIN #Table1 t1 ON t2.[Date] = t1.[Date]
ORDER BY t2.[Date]
OUTPUT:
Date StartingAum DepContr withdra
----------------------- ----------- ----------- -----------
2010-01-01 00:00:00.000 0 60 15
2010-02-01 00:00:00.000 0 70 25
2010-03-01 00:00:00.000 0 80 15
2010-04-01 00:00:00.000 0 30 89
2010-05-01 00:00:00.000 0 40 15
2010-06-01 00:00:00.000 0 25 85
2010-07-01 00:00:00.000 120 16 17
2010-08-01 00:00:00.000 220 19 21
2010-09-01 00:00:00.000 320 68 79
I think you should have a look at this page: http://www.w3schools.com/sql/sql_union.asp
That might be helpful?

Resources