SQL Query Profit and Loss - sql

I have two tables in SQL Server: TblGroup and TblAmount
TblGroup
Grp_Id Grp_Name GrpType
------ -------------- -----------
1 Direct Incomes Income
2 Indirect Incomes Income
3 Misc. Expences Expence
4 Other Incomes Income
5 Purchases Expence
6 Selling Expences Expence
7 Sales Income
TblAmount
Grp_Id Amount
------ -------
1 2000
2 1500
3 3000
4 5000
5 4000
6 1000
7 4500
This is the output that I need:
Income Amount Expence Amount
------------- ----- ------------- ----------
Direct Incomes 2000 Misc. Expences 3000
Indirect Incomes 1500 Purchases 4000
Other Incomes 5000 Selling Expences 1000
Sales 4500
This is my query, but not getting the right result:
declare #TblGroup as table (Grp_Id int, Grp_Name varchar(50), GrpType varchar(20))
insert into #TblGroup values
(1,'Direct Incomes','Income')
,(2,'Indirect Incomes','Income')
,(3,'Misc. Expences','Expence')
,(4,'Other Incomes','Income')
,(5,'Purchases','Expence')
,(6,'Selling Expences','Expence')
,(7,'Sales','Income')
declare #TblAmount as table(Grp_Id int,Amount int)
insert into #TblAmount values
(1,2000)
,(2,1500)
,(3,3000)
,(4,5000)
,(5,4000)
,(6,1000)
,(7,4500)
select * from (
SELECT Grp_Name AS Income, Amount AS Amount
FROM #TblGroup g
LEFT JOIN #TblAmount a ON g.Grp_Id = a.Grp_Id
WHERE GrpType = 'Income') as Income
JOIN (
SELECT Grp_Name AS Expence, Amount AS Amount
FROM #TblGroup g
LEFT JOIN #TblAmount a ON g.Grp_Id = a.Grp_Id
WHERE GrpType = 'Expence') as Expence on Income.Income<>Expence.Expence
Where duplicate Income and Expense is coming in an output, How could I overcome this Issue.

This is a fairly simple Left Join question, here's half of the solution
SELECT GrpType AS Income, TblAmount.Amount AS Amount
FROM TblGroup
LEFT JOIN TblAmount
ON TblGroup.Grp_Id = TblAmount.Grp_Id
WHERE GrpType = "Income"
You should be able to guess how to get the other result.

CREATE TABLE TblGroup ( Grp_Id int, Grp_Name varchar(200),
GrpType varchar(200));
INSERT INTO TblGroup
VALUES(1,
'Direct Incomes',
'Income');
INSERT INTO TblGroup
VALUES(2,
'Indirect Incomes',
'Income');
INSERT INTO TblGroup
VALUES(3,
'Misc. Expences',
'Expence');
INSERT INTO TblGroup
VALUES(4,
'Other Incomes',
'Income');
INSERT INTO TblGroup
VALUES(5,
'Purchases',
'Expence');
INSERT INTO TblGroup
VALUES(6,
'Selling Expences',
'Expence');
INSERT INTO TblGroup
VALUES(7,
'Sales',
'Income');
CREATE TABLE TblAmount ( Grp_Id int, amount int);
INSERT INTO TblAmount
VALUES(1,
2000);
INSERT INTO TblAmount
VALUES(2,
1500);
INSERT INTO TblAmount
VALUES(3,
3000);
INSERT INTO TblAmount
VALUES(4,
5000);
INSERT INTO TblAmount
VALUES(5,
4000);
INSERT INTO TblAmount
VALUES(6,
1000);
INSERT INTO TblAmount
VALUES(7,
4500);
SELECT DISTINCT Income,
c.amount,
Expence,
d.amount from
(SELECT a.Grp_Id, CASE
WHEN GrpType='Income' THEN Grp_Name
END AS Income, b.amount
FROM TblGroup a
INNER JOIN TblAmount b ON a.Grp_Id=b.Grp_Id)c
LEFT OUTER JOIN
(SELECT a.Grp_Id,
CASE
WHEN GrpType='Expence' THEN Grp_Name
END AS Expence,
amount
FROM TblGroup a
INNER JOIN TblAmount b ON a.Grp_Id=b.Grp_Id)d ON c.Grp_Id=d.Grp_Id;

SELECT TG.Grp_Name AS Income, TA.Amount
FROM TblGroup TG, TblAmount TA
WHERE TA.Grp_Id = TG.Grp_Id
AND TG.GrpType = 'Income';
SELECT TG.Grp_Name AS Expence, TA.Amount
FROM TblGroup TG, TblAmount TA
WHERE TA.Grp_Id = TG.Grp_Id
AND TG.GrpType = 'Expence';
First query will give you the details for grpType income and the second gives the details for grpType expense.
A simple statement in the where clause can give you the output. You can also try it with SQL joins. But I prefer to go easy.

At last I got the Answer, Here is the solution.
declare #TblGroup as table (Grp_Id int, Grp_Name varchar(50), GrpType varchar(20))
insert into #TblGroup values
(1,'Direct Incomes','Income')
,(2,'Indirect Incomes','Income')
,(3,'Misc. Expences','Expence')
,(4,'Other Incomes','Income')
,(5,'Purchases','Expence')
,(6,'Selling Expences','Expence')
,(7,'Sales','Income')
declare #TblAmount as table(Grp_Id int,Amount int)
insert into #TblAmount values
(1,2000)
,(2,1500)
,(3,3000)
,(4,5000)
,(5,4000)
,(6,1000)
,(7,4500)
SELECT Row_Number() OVER (ORDER BY (SELECT 1)) as SNo, TG.Grp_Name AS Income, TA.Amount into #Incme
FROM #TblGroup TG, #TblAmount TA
WHERE TA.Grp_Id = TG.Grp_Id
AND TG.GrpType = 'Income';
SELECT Row_Number() OVER (ORDER BY (SELECT 1)) as SNo , TG.Grp_Name AS Expence, TA.Amount into #Expnse
FROM #TblGroup TG, #TblAmount TA
WHERE TA.Grp_Id = TG.Grp_Id
AND TG.GrpType = 'Expence';
DECLARE #TblMain as table(Income varchar(50), Amount int, Expense varchar(50), Amount2 int)
DECLARE #row INT = 1
,#ROWCOUNT int
,#RowCount_Incme INT = (select COUNT(*) from #Incme)
,#RowCount_Expnse INT = (select COUNT(*) from #Expnse)
set #ROWCOUNT = case when #RowCount_Incme > #RowCount_Expnse then #RowCount_Incme else #RowCount_Expnse end
WHILE (#ROW <= #ROWCOUNT)
BEGIN
insert into #TblMain(Income, Amount,Expense,Amount2) (
select Income, Amount
,(select Expence from #Expnse where SNo=#row)
,(select Amount from #Expnse where SNo=#row)
from #Incme where SNo=#row
)
SET #ROW = #ROW+1
END
select * from #TblMain
drop table #Incme
drop table #Expnse

Related

Compare two tables and find not matched price SQL Server

create table #tmp1
(
name varchar(100),
price decimal(10, 2)
)
insert into #tmp1 values('Test', 200.00)
insert into #tmp1 values('Test', 100.00)
insert into #tmp1 values('Test', 300.00)
insert into #tmp1 values('Test1', 500.00)
insert into #tmp1 values('Test2', 300.00)
create table #tmp
(
name varchar(100),
price decimal(10,2)
)
insert into #tmp values('Test', 200.00)
insert into #tmp values('Test', 100.00)
insert into #tmp values('Test', 400.00)
insert into #tmp values('Test1', 600.00)
insert into #tmp values('Test3', 300.00)
I have two tables with comparing parameter Name and find not matched price.
Name should match and price will be differ.
Expected output:
Name Price Price
------------------------------
Test1 600.00 500.00
Test 300.00 400.00
Try this
SELECT *
FROM #tmp a
INNER JOIN #tmp1 b ON a.name=b.name AND a.PRICE <> b.PRICE
UPDATED : AS per your below comment you wants to consider order of insertion as well,
;WITH tmp AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY NAME) RN
FROM #tmp
),tmp1 AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY NAME) RN
FROM #tmp1
)
SELECT a.name,a.price,b.price
FROM tmp a
INNER JOIN tmp1 b ON a.name=b.name AND a.RN=b.RN AND a.PRICE <> b.PRICE

CTE Recursive Queries

I have a table with records of employees that shows a relationship of employees and who they report to:
From_ID position TO_ID position
----------------------------------------
1 Lowest_employee 3 employee
3 employee 4 employee
4 employee 5 BOSS
2 Lowest_employee 6 employee
6 employee 3 employee
10 Lowest_employee 50 BOSS2
I would like to show results that look like this, with the employee / boss IDs:
EmployeeID BossID
--------------------
1 5
2 5
10 50
This means employees 1 and 2 report to ID 5 and employee 10 reports to another boss with ID 50.
I know I need to use CTE and Recursive Queries, but cannot understand how it can be done, I'm newer to CTE Recursive Queries.
I read this article but it doesn't make any sense to me MS link
Any help with the query required to achieve this would be useful.
This includes setting up test data, however I think this is what you want:
Test Data:
DECLARE #Table TABLE
(
From_ID int,
TO_ID int
)
INSERT INTO #Table VALUES(1,3)
INSERT INTO #Table VALUES(3,4)
INSERT INTO #Table VALUES(4,5)
INSERT INTO #Table VALUES(2,6)
INSERT INTO #Table VALUES(6,3)
INSERT INTO #Table VALUES(10,50)
Query to get answer:
;WITH Hierarchy (Employee, Superior, QueryLevel)
AS
(
--root is all employees that have no subordinates
SELECT E.From_ID, E.TO_ID, 1
FROM #Table E
LEFT
JOIN #Table S
ON S.TO_ID = E.From_ID
WHERE S.TO_ID IS NULL
--recurse up tree to final superior
UNION ALL
SELECT H.Employee, S.TO_ID, H.QueryLevel + 1
FROM Hierarchy H
JOIN #Table S
ON S.From_ID = H.Superior
)
SELECT Employee, Superior
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Employee ORDER BY QueryLevel DESC) AS RowNumber
FROM Hierarchy
) H
WHERE RowNumber = 1
Essentially, this works by :
1) get all employees with no reportees (the root)
2) recurses up through the bosses, recording the 'level'
3) use over/partition to select only the 'final' boss
WITH q (employee, boss) AS
(
SELECT fromId, toId
FROM mytable
WHERE fromId NOT IN
(
SELECT toId
FROM mytable
)
UNION ALL
SELECT employee, toId
FROM q
JOIN mytable t
ON t.fromId = boss
)
SELECT *
FROM q
WHERE boss NOT IN
(
SELECT fromId
FROM mytable
)
You could try something like this?
DECLARE #Employees TABLE (
EmployeeId INT,
PositionName VARCHAR(50),
ReportsToId INT);
INSERT INTO #Employees VALUES (1, 'Driver', 3);
INSERT INTO #Employees VALUES (3, 'Head of Driving Pool', 4);
INSERT INTO #Employees VALUES (4, 'Corporate Flunky', 5);
INSERT INTO #Employees VALUES (2, 'Window Cleaner', 6);
INSERT INTO #Employees VALUES (6, 'Head of Office Services', 3);
INSERT INTO #Employees VALUES (10, 'Minion', 50);
INSERT INTO #Employees VALUES (5, 'BOSS', NULL);
INSERT INTO #Employees VALUES (50, 'BOSS2', NULL);
WITH Employees AS (
SELECT
EmployeeId,
1 AS [Level],
EmployeeID AS [Path],
ISNULL(ReportsToId, EmployeeId) AS ReportsToId
FROM
#Employees
WHERE
ReportsToId IS NULL
UNION ALL
SELECT
e.EmployeeID,
x.[Level] + 1 AS [Level],
x.[Path] + e.EmployeeID AS [Path],
x.ReportsToId
FROM
#Employees e
INNER JOIN Employees x ON x.EmployeeID = e.ReportsToId)
SELECT
ec.EmployeeId,
e.PositionName,
ec.[Level],
CASE WHEN ec.ReportsToId = ec.EmployeeId THEN NULL ELSE ec.ReportsToId END AS ReportsToId --Can't really report to yourself
FROM
Employees ec
INNER JOIN #Employees e ON e.EmployeeId = ec.EmployeeId
ORDER BY
ec.[Path];

SQL Server Getting where an data object was based in a Period of Time given Track Info

I have a doubt on how to conclude this in SQL Server 2008 R2.
I have a table that has some inputs and this inputs have a Parent tag and a timestamp.
Sometimes these objects have their parent Tag changed in a timestamp. This parent tag can change from time to time.
Let´s suppose that I have the table below. My current table has millions of data with different ObjectIDs. Seeing the Table, it is easy to see that the ParentID was changed in the timestamps 3 to 4, 6 to 7 and 8 to 9.
ProductID ParentID DateID value
-------- --------- ------- -------------
100 1 1 325,2
100 1 2 326,2
100 1 3 329,6
100 2 4 335,2
100 2 5 336,5
100 2 6 338,3
100 3 7 339,2
100 3 8 342,1
100 1 9 343,7
100 1 10 355,6
100 1 11 385,8
The Answer I want is to which ParentID the ObjectID belonged and the Start and End timestamp and what was the delta value between the timestamps (Timestamp = TS)
ProductID ParentID DateID_Start DateID_End DeltaValue
-------- --------- ---------- -------- ----------
100 1 1 4 10,0
100 2 4 7 4,0
100 3 7 9 4,5
100 1 9 11 42,1
What I have Accomplish so far is getting when there is a change, but it only gives me the changes, but not the table above.
ObjectID ParentID_Old ParentID_New DateID_Changed
-------- ------------ ------------ ------------
100 1 2 3 to 4
100 2 3 6 to 7
100 3 1 8 to 9
Here are the code to generate the table and the test inserts. Below as well is the Select to get the changes.
--Initial Insert Code
IF OBJECT_ID('tempdb..#Trackings') Is Not Null
Drop table #Trackings
Create Table #Trackings
(
ProductID bigint
, value float
, StoreID int
, DateID int
, Aux_Row_Number int
)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)
And the SQL to get the changes I am using:
Select ISNULL(A.StoreID,-1)
, ISNULL(B.StoreID,-1)
, A.ProductID
, A.value
, B.value
, A.DateID
, B.DateID
From #Trackings A
Join #Trackings B
On A.ProductID = B.ProductID
And A.Aux_Row_Number + 1 = B.Aux_Row_Number
And ISNULL(A.StoreID,-1) <> ISNULL(B.StoreID,-1)
Any lights ideas Guys?
Thanks in advance!
EDITED: Just a little bit more "Business" info: ParentID would be like a store a product is and DateID the Time that it arrived there. So let's suppose that productID 100 is in the ParentID 1, it means that in the DateID 1 the productID 100 entered in Store 1. So for some reason it moved to Store 2 in DatedID 4. So my first row in the answer table means that ProductID 100 was in the StoreID 1 from DateID 1 up to DateID 4. The productID 100 then stayed in StoredID 2 from DateID 4 up to 7, then changed to StoredID 3 and finally it came back to StoreID 1 from DateID 9 up to our last DateID in the DateID range "selected". So that's why the answer table has 2 lines with ParentID 1.
OK, try this, using your updated sample data:
Declare #Trackings table
(
ProductID bigint
, value float
, StoreID int
, DateID int
, Aux_Row_Number int
)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)
;
with t
as (select *, ROW_NUMBER() over (order by dateid) as rn
from #Trackings ),
cte1
(Productid,
Storeid,
DateID,
value,
rn,
set1)
as
(select ProductID, StoreID, DateID, value, rn , 1
from t
where rn = 1
union all
select t.productID, t.storeID, t.dateID, t.value, t.rn,
case when
cte1.Storeid = t.storeID then cte1.set1 else cte1.set1+1 end
from t join cte1 on t.rn = cte1.rn+1)
,
t2 as (select Productid, Storeid, set1, MIN(CAST(DateID as int)) as tmi, max(dateid) as tma
from cte1
group by Productid, Storeid, set1)
select t3.Productid, t3.Storeid, t3.set1, t3.date_min, t3.date_max, u.value - t.value
from
(select a.Productid, a.Storeid, a.set1, a.tmi as date_min, coalesce(b.tmi, a.tma) as date_max
from t2 a left join t2 b
on a.set1 + 1 = b.set1) t3 join #Trackings t
on t3.date_min = t.DateID
join #Trackings u
on t3.date_max = u.DateID
order by set1
The "Value" column confused me, as you are using commas (,) instead of periods (.) to separate the integer from the decimal part of your float.
I finally found a solution that based on my Initial Table has a better performance than using CTE and as sugested by https://stackoverflow.com/users/2522030/mike-abramczyk (the real table has 5k entries and using the his suggestion was taking a long time).
After querying the search table, I added two lines to the table for each ProductID. These lines would receive a dummy StoreID (i.e. -9999): one with a Min(DateID) - 1 and another One with a Max(DateID) + 1.
Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Min(Aux_Row_Number)-1 Aux_Row_Number,-9999 as StoreID, min(DateID)-1 as DateID,ProductID,Min(value)
From #Trackings
group by ProductID
Order by ProductID
Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Max(Aux_Row_Number)+1 Aux_Row_Number,-9999 as StoreID, max(DateID)+1 as DateID,ProductID,Max(value)
From #Trackings
group by ProductID
Order by ProductID
Then, I used the Query I posted to get the changes. So I could get the Change from Dummy(-9999) to the real StoreID (1) and the last change from a real StoreID(3) to Dummy(-9999).
select ISNULL(A.StoreID,-1)
, ISNULL(B.StoreID,-1)
, A.ProductID
, A.value
, B.value
, A.DateID
, B.DateID
, ROW_NUMBER() OVER (Partition by B.ProductID Order by A.DateID)
from #Trackings A
Join #Trackings B
On A.ProductID = B.ProductID
And A.Aux_Row_Number + 1 = B.Aux_Row_Number
AND ISNULL(A.StoreID,0) <> ISNULL(B.StoreID ,0)
This was the Crucial Step! Now I have I can create the result table with the DateIDs of the changes I was looking for. The Aux_Row_Number Column helped get a sequence in the changes to each product using (think that the last query has create the table #ProductStoreChanges - I will be posting the entire Soltion below):
select A.ID_FinalStore,A.DateID_Final,B.DateID_Final,A.ProductID,B.value_2,A.value_2,B.value_2 - A.value_2 DeltaValue
from #ProductStoreChanges A
Join #ProductStoreChanges B
On (A.Aux_Row_Number + 1 = B.Aux_Row_Number)
And A.ProductID = B.ProductID
Order by A.DateID_Final
Here is the Final Solution:
IF OBJECT_ID('tempdb..#Trackings') Is Not Null
Drop table #Trackings
IF OBJECT_ID('tempdb..#ProductStoreChanges') Is Not Null
Drop table #ProductStoreChanges
Create Table #Trackings
(
ProductID bigint
, value float
, StoreID int
, DateID int
, Aux_Row_Number int
, flg_changed bit Default(0)
)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)
Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Min(Aux_Row_Number)-1 Aux_Row_Number,-9999 as StoreID, min(DateID)-1 as DateID,ProductID,Min(value)
From #Trackings
group by ProductID
Order by ProductID
Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Max(Aux_Row_Number)+1 Aux_Row_Number,-9999 as StoreID, max(DateID)+1 as DateID,ProductID,Max(value)
From #Trackings
group by ProductID
Order by ProductID
CREATE TABLE #ProductStoreChanges
(
ID_InitialStore INT
, ID_FinalStore INT
, ProductID INT
, value_1 BIGINT
, value_2 BIGINT
, DateID_Initial BIGINT
, DateID_Final BIGINT
, Aux_Row_Number INT
)
INSERT INTO #ProductStoreChanges
(
ID_InitialStore
, ID_FinalStore
, ProductID
, value_1
, value_2
, DateID_Initial
, DateID_Final
, Aux_Row_Number
)
select ISNULL(A.StoreID,-1)
, ISNULL(B.StoreID,-1)
, A.ProductID
, A.value
, B.value
, A.DateID
, B.DateID
, ROW_NUMBER() OVER (Partition by B.ProductID Order by A.DateID)
from #Trackings A
Join #Trackings B
On A.ProductID = B.ProductID
And A.Aux_Row_Number + 1 = B.Aux_Row_Number
AND ISNULL(A.StoreID,0) <> ISNULL(B.StoreID ,0)
select A.ID_FinalStore,A.DateID_Final,B.DateID_Final,A.ProductID,B.value_2,A.value_2,B.value_2 - A.value_2 DeltaValue
from #ProductStoreChanges A
Join #ProductStoreChanges B
On (A.Aux_Row_Number + 1 = B.Aux_Row_Number)
And A.ProductID = B.ProductID
Order by A.DateID_Final

comparing two colums in sqlserver and returing the remaining data

I have two tables. First one is student table where he can select two optional courses and other table is current semester's optional courses list.
When ever the student selects a course, row is inserted with basic details such as roll number, inserted time, selected course and status as "1". When ever a selected course is de-selected the status is set as "0" for that row.
Suppose the student has select course id 1 and 2.
Now using this query
select SselectedCourse AS [text()] FROM Sample.dbo.Tbl_student_details where var_rollnumber = '020803009' and status = 1 order by var_courseselectedtime desc FOR XML PATH('')
This will give me the result as "12" where 1 is physics and 2 is social.
the second table holds the value from 1-9
For e.g course id
1 = physics
2 = social
3 = chemistry
4 = geography
5 = computer
6 = Spoken Hindi
7 = Spoken English
8 = B.EEE
9 = B.ECE
now the current student has selected 1 and 2. So on first column, i get "12" and second column i need to get "3456789"(remaining courses).
How to write a query for this?
This is not in single query but is simple.
DECLARE #STUDENT AS TABLE(ID INT, COURSEID INT)
DECLARE #SEM AS TABLE (COURSEID INT, COURSE VARCHAR(100))
INSERT INTO #STUDENT VALUES(1, 1)
INSERT INTO #STUDENT VALUES(1, 2)
INSERT INTO #SEM VALUES(1, 'physics')
INSERT INTO #SEM VALUES(2, 'social')
INSERT INTO #SEM VALUES(3, 'chemistry')
INSERT INTO #SEM VALUES(4, 'geography')
INSERT INTO #SEM VALUES(5, 'computer')
INSERT INTO #SEM VALUES(6, 'Spoken Hindi')
INSERT INTO #SEM VALUES(7, 'Spoken English')
INSERT INTO #SEM VALUES(8, 'B.EEE')
INSERT INTO #SEM VALUES(9, 'B.ECE')
DECLARE #COURSEIDS_STUDENT VARCHAR(100), #COURSEIDS_SEM VARCHAR(100)
SELECT #COURSEIDS_STUDENT = COALESCE(#COURSEIDS_STUDENT, '') + CONVERT(VARCHAR(10), COURSEID) + ' ' FROM #STUDENT
SELECT #COURSEIDS_SEM = COALESCE(#COURSEIDS_SEM , '') + CONVERT(VARCHAR(10), COURSEID) + ' ' FROM #SEM WHERE COURSEID NOT IN (SELECT COURSEID FROM #STUDENT)
SELECT #COURSEIDS_STUDENT COURSEIDS_STUDENT, #COURSEIDS_SEM COURSEIDS_SEM
try this:
;WITH CTE as (select ROW_NUMBER() over (order by (select 0)) as rn,* from Sample.dbo.Tbl_student_details)
,CTE1 As(
select rn,SselectedCourse ,replace(stuff((select ''+courseid from course_details for xml path('')),1,1,''),SselectedCourse,'') as rem from CTE a
where rn = 1
union all
select c2.rn,c2.SselectedCourse,replace(rem,c2.SselectedCourse,'') as rem
from CTE1 c1 inner join CTE c2
on c2.rn=c1.rn+1
)
select STUFF((select ''+SselectedCourse from CTE1 for xml path('')),1,0,''),(select top 1 rem from CTE1 order by rn desc)

How to create sql procedure for calculating Total dues

Can anyone help me by showing a create procedure statement for calculating Total Dues from three tables? Here are the tables along with their data ..
Table_1
accountno shipername shiperaddress Executivename
001 john 123, London Paul
002 Robi 127, China Soma
Table_2
Executivename shipername shiperaddress accountno currentamount anotheramount
paul john 123,london 001 10500 12000
soma robi 127,china 002 11000 6800
Table_3
accountno Date ReceivedAmount MoneyReceiptNo
001 1/1/2012 6500 G 256412
002 1/2/2012 5200 D 246521
Here I am to mention that the Total Dues will be calculated as
(currentamount + anotheramount) - receivedamount
I tried to do that by the following stored procedure.
CREATE PROCEDURE [dbo].[rptexetotaldues] #Executivename varchar(20)
AS BEGIN
select
table_1.Executivename,
sum(table_2.currentamount + table_2.anotheramount
- table_3.receivedamount ) as TotalDues
from
table_1
full join
table_2 on table_1.accountno = table_2.accountno
join
table_3 on table_3.accountno = table_1.accountno
where
table_1.Executivename = #Executivename
group by
table_1.Executivename
end
But that doesn't work. Please somebody help me.
Your sample worked for me. The only thing I changed is "Date" to transdate. I strongly recommend avoiding "Date" as a column name. I also changed the aliasing a bit, but that should have been allright. I thinkg #Gordon Linoff is right - you could have an issue with NULLS.
DECLARE #table_1 TABLE (accountno char(5), shipername char(20), shiperaddress char(40), Executivename varchar(20))
INSERT INTO #table_1 VALUES ('001', 'john', '123, London', 'Paul')
INSERT INTO #table_1 VALUES ('002','Robi','127, China','Soma')
DECLARE #table_2 TABLE (Executivename varchar(20), shipername char(20), shiperaddress char(40),
accountno char(20), currentamount decimal(10,2), anotheramount decimal(10,2))
INSERT INTO #table_2 VALUES ('paul', 'john','123,london','001',10500, 12000)
INSERT INTO #table_2 VALUES ('soma', 'robi', '127,china', '002', 11000, 6800)
DECLARE #table_3 TABLE(accountno char(20), tranDate datetime, ReceivedAmount decimal(10,2), MoneyReceiptNo char(10))
INSERT INTO #table_3 VALUES ('001', '1/1/2012', 6500, 'G 256412')
INSERT INTO #table_3 VALUES ('002', '1/2/2012', 5200,'D 246521')
DECLARE #Executivename varchar(20)
--SET #Executivename = 'Paul'
SET #Executivename = 'Soma'
select
tb1.Executivename,
sum(tb2.currentamount + tb2.anotheramount - tb3.receivedamount ) as TotalDues
from
#table_1 tb1
full join #table_2 tb2 on tb1.accountno = tb2.accountno
join #table_3 tb3 on tb3.accountno = tb1.accountno
where
tb1.Executivename=#Executivename group by tb1.Executivename
Here are my results:
Executivename TotalDues
Soma 12600.00
I can think of two problems. First is that the account number is duplicated in either table 1 or table 2. This will add extra rows.
The second is that there are rows in table three that are not in table 2. This means that the addition within the sum is NULL because one of the values is NULL. You can fix this in one of these ways:
sum(table_2.currentamount) + sum(table_2.anotheramount) - sum(table_3.receivedamount)
or
sum(coalesce(table_2.currentamount, 0.0) + coalesce(table_2.anotheramount, 0.0) - coalesce(table_3.receivedamount, 0.0) ) as TotalDues
I think it would be more straightforward as a UNION query, example below:
CREATE PROCEDURE [dbo].[rptexetotaldues] #Executivename varchar(20)
AS BEGIN
SELECT SUB.ACCOUNTNO, SUM(SUB.DUE) AS TOTALDUE FROM
(SELECT ACCOUNTNO
, CURRENTAMOUNT AS DUE
FROM TABLE_2
INNER JOIN TABLE_1 -- WILL ONLY WORK IF ACCOUNTNO IS UNIQUE WITHIN TABLE_1
ON TABLE_1.ACCOUNTNO = TABLE2.ACCOUNTNO
WHERE TABLE_1.EXECUTIVENAME = #Executivename
UNION ALL
SELECT ACCOUNTNO
, ANOTHERAMOUNT AS DUE
FROM TABLE_2
INNER JOIN TABLE_1
ON TABLE_1.ACCOUNTNO = TABLE2.ACCOUNTNO
WHERE TABLE_1.EXECUTIVENAME = #Executivename
UNION ALL
SELECT ACCOUNTNO
, -RECEIVEDAMOUNT AS DUE -- NOTE NEGATIVE SIGN
FROM TABLE 3
INNER JOIN TABLE_1
ON TABLE_1.ACCOUNTNO = TABLE3.ACCOUNTNO
WHERE TABLE_1.EXECUTIVENAME = #Executivename
) SUB
GROUP BY SUB.ACC