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