How to fetch self referenced column value in sql - sql-server

I have two tables with column
CREATE TABLE Dept(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Next_ID] [int] NULL,
[Name] [varchar](50) NOT NULL,
[Bundle_ID] [int] NULL
)
And
CREATE TABLE Bundle(
[Bundle_ID] [int] NOT NULL,
[Bundle_Name] [varchar](40) NOT NULL
)
I would like to fetch nextID name so i tried
SELECT dept.ID, dept.Next_ID, currentbundle.Bundle_Name CurrentBundleName
FROM Dept dept
join Bundle currentbundle on currentbundle.Bundle_ID = dept.Bundle_ID
join dept dept1 on dept1.Next_ID=dept.ID
With this, I get only currentBundleName. How to fetch nextbundlename?
I would like to have output like this
ID NextID CurrentBundleName NextBundleName
********************************************************
1 3 template excel
3 4 excel word
4 NULL word NULL

CREATE TABLE #Dept(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Next_ID] [int] NULL,
[Name] [varchar](50) NOT NULL,
[Bundle_ID] [int] NULL
)
CREATE TABLE #Bundle(
[Bundle_ID] [int] NOT NULL,
[Bundle_Name] [varchar](40) NOT NULL
)
INSERT INTO #Bundle
( Bundle_ID, Bundle_Name )
VALUES
( 1, 'One' ),
( 2, 'Two' ),
( 3, 'Three' ),
( 4, 'Four' )
INSERT INTO #Dept
( Next_ID, Name, Bundle_ID )
VALUES
( NULL, 'First', 1),
( 1, 'Second', 2),
( 2, 'Third', 3),
( 3, 'Fouth', 4)
select
d.ID,
d.Name AS DeptName,
d2.ID AS NextDeptId,
d2.Name AS NextDeptName,
b.Bundle_Name AS BundleName,
b2.Bundle_Name AS NextBundleName
FROM #Dept d
JOIN #Bundle b ON b.Bundle_ID = d.Bundle_ID
LEFT JOIN #Dept d2 ON d2.id=d.Next_ID
LEFT JOIN #Bundle b2 ON b2.Bundle_ID = d2.Bundle_ID
DROP TABLE #Bundle
DROP TABLE #Dept
Corrected Results:
ID DeptName NextDeptId NextDeptName BundleName NextBundleName
1 First NULL NULL One NULL
2 Second 1 First Two One
3 Third 2 Second Three Two
4 Fouth 3 Third Four Three

Please try this :
SELECT d.id,
d.next_id,
b.Bundle_Name current_bundle_name,
b1.Bundle_Name AS next_bundle_name
FROM dept d
INNER JOIN bundle b ON b.Bundle_ID = d.Bundle_ID
LEFT JOIN bundle b1 ON b1.Bundle_ID = d.Next_ID

Related

Select to PIVOT

I have table in SQL as :
DefultDim Name, DisplayValue
-------------------------------------
5637145329, B_MainSector, 4
5637145329, C_SecondSector, 401
5637145329, D_ThirdSection, 40100
5637145329, E_Vendor, 0032
I want to use select to see as :
DefultDim, B_MainSector, C_SecondSector, D_ThirdSection, E_Vendor
--------------------------------------------------------------------
5637145329 4 401 40100 0032
I use this code :
select DEFAULTDIMENSION AS FULLDIM ,[0] AS B_MainSector ,[1] AS C_SecondSector ,[2] AS D_ThirdSection ,[3] AS E_Vendor
from
(select DEFAULTDIMENSION,NAME,RECID,DISPLAYVALUE from DEFAULTDIMENSIONVIEW )
P PIVOT (max(DISPLAYVALUE)
for DISPLAYVALUE in([0],[1],[2],[3])) as PVT
But results seem as :
DefultDim B_MainSector C_SecondSector D_ThirdSection E_Vendor
--------------------------------------------------------------------
5637145329, NULL, NULL, NULL, NULL
5637145329, NULL, NULL, NULL, NULL
5637145329, NULL, NULL, NULL, NULL
5637145329, NULL, NULL, NULL, NULL
Kindly help.
You can try the following Pivot query
create table #Temp (DefultDim Varchar(15), Name Varchar(15), DisplayValue Varchar(5))
Insert Into #Temp Values ('5637145329', 'B_MainSector', '4'),
('5637145329', 'C_SecondSector', '401'),
('5637145329', 'D_ThirdSection', '40100'),
('5637145329', 'E_Vendor', '0032')
select DefultDim, B_MainSector, C_SecondSector, D_ThirdSection, E_Vendor
from
(
select DefultDim, DisplayValue, Name
from #Temp
) d
pivot
(
max(DisplayValue)
for Name in (B_MainSector, C_SecondSector, D_ThirdSection, E_Vendor)
) piv;
You can find the live demo Live Demo Here
I do not have any problems renaming the values
SELECT DefaultDim
,Name
,[4] AS B_itsMe
,[401] AS i_MadeIt
,[32] AS O_K
,[40100] AS Fix_This
FROM(
SELECT * FROM temp.dbo.DefaultDimensionView
PIVOT(
MAX(DisplayValue)
FOR DisplayValue
IN ([4], [401], [32], [40100])
) AS Piv_DisplayValue
) AS R
Sample data

SQL Query for Outer Join with Group By

I have the Months Table with MonthName, MonthNumber and Fiscal Year starts with July so I have assigned the values to the months like
MonthName=July and MonthNumber=1
MonthName=August and MonthNumber=2.
I have another Domain table BudgetCategory and it has BudgetCategoryId, BudgetCategoryName.
The PurchaseOrder table has OrderID, PurchaseMonth, BudgetCategoryId.
Now I want the query to find out the Monthly Purchases SUM(TotalCost) for every BudgetCategory. If there are no purchases for any BudgetCategoryId I want to display the zero in report.
Schema of Table:
CREATE TABLE [dbo].[BudgetCategory](
[BudgetCategoryId] [numeric](18, 0) NOT NULL,
[BudgetCategoryName] [varchar](50) NULL,
[TotalBudget] [nvarchar](50) NULL)
CREATE TABLE [dbo].[PurchaseOrder](
[OrderId] [bigint] NOT NULL,
[BudgetCategoryId] [bigint] NULL,
[PurchaseMonth] [nvarchar](50) NULL,
[QTY] [bigint] NULL,
[CostPerItem] [decimal](10, 2) NULL,
[TotalCost] [decimal](10, 2) NULL)
CREATE TABLE [dbo].[MonthTable](
[MonthNumber] [bigint] NULL,
[MonthName] [nvarchar](30) NULL)
Try this:
select a.BudgetCategoryName,
ISNULL(c.MonthName,'No purchase') as Month,
sum(ISNULL(TotalCost,0)) as TotalCost
from #BudgetCategory a left join #PurchaseOrder b on a.BudgetCategoryId = b.BudgetCategoryId
left join #MonthTable c on b.PurchaseMonth = c.[MonthName]
group by a.BudgetCategoryName,c.MonthName
order by a.BudgetCategoryName
Tested with this data
INSERT #BudgetCategory
VALUES (1,'CategoryA',1000),
(2,'CategoryB',2000),
(3,'CategoryC',1500),
(4,'CategoryD',2000)
INSERT #PurchaseOrder (OrderId,BudgetCategoryId,TotalCost,PurchaseMonth)
VALUES (1,1,550,'July'),
(2,1,700,'July'),
(3,2,600,'August')
INSERT #MonthTable
VALUES
(1,'July'),
(2,'August')
It will produce this results:
Let me know if this could help you
SELECT b.*, m.MonthNumber, q.[BudgetCategoryId], q.[PurchaseMonth], ISNULL(q.[TotalCost],0)
FROM [dbo].[BudgetCategory] b
LEFT JOIN
(
SELECT [BudgetCategoryId], [PurchaseMonth], sum([TotalCost]) [TotalCost]
FROM [dbo].[PurchaseOrder] p
GROUP BY p.[BudgetCategoryId], [PurchaseMonth]
) q ON b.BudgetCategoryId = q.BudgetCategoryId
LEFT JOIN [dbo].[MonthTable] m ON q.[PurchaseMonth] = m.[MonthName]

SQL Server table design to define WHERE condition

I have an existing Stored procedure which has lots of hard-coding with IF conditions. The procedure checks the values of following input fields and displays relevant message: The fields are:
• BrandId
• ProductId
• SchemeId
• RegionId
The existing Message table:
MsgId MsgText
1 AAAA
2 BBBB
3 CCCC
4 MMMM
Existing stored proc. pseudo code:
IF(BrandId in (5,10))
IF(#ProductId in (5))
SELECT ‘BBBB’ as MsgText
END IF
END IF
IF(SchemeId in (1,5,10))
SELECT ‘AAAA’ as MsgText
IF(SchemeId =2 AND #RegionId=4)
SELECT ‘BBBB’ as MsgText
IF (#RegionId=6)
SELECT ‘MMMM’ as MsgText
In order to remove hard-coding and re-writing the procedure cleanly from scratch, I want to design new tables which will store "MsgId"s against a BrandId/ProdId/PlanId/SchemeId value or against a combination of these fields (e.g SchemeId =2 AND RegionId=4).With this kind of design I can directly fetch the relevant MsgId against a specific field or combination of fields.
Could anybody suggest table designs to meet the requirement?
Based on your responses to the comments, this might work out.
create table dbo.[Messages] (
MessageId int not null
, MessageText nvarchar(1024) not null
, constraint pk_Messages primary key clustered (MessageId)
);
insert into dbo.[Messages] (MessageId,MessageText) values
(1,'AAAA')
, (2,'BBBB')
, (13,'MMMM');
create table dbo.Messages_BrandProduct (
BrandId int not null
, ProductId int not null
, MessageId int not null
, constraint pk_Messages_BrandProduct primary key clustered
(BrandId, ProductId, MessageId)
);
insert into dbo.Messages_BrandProduct (BrandId, ProductId, MessageId) values
(5,5,2)
,(10,5,2);
create table dbo.Messages_SchemeRegion (
SchemeId int not null
, RegionId int not null
, MessageId int not null
, constraint pk_Messages_SchemeRegion primary key clustered
(SchemeId, RegionId, MessageId)
);
insert into dbo.Messages_SchemeRegion (SchemeId, RegionId, MessageId)
select SchemeId = 1, RegionId , MessageId = 1 from dbo.Regions
union all
select SchemeId = 5, RegionId , MessageId = 1 from dbo.Regions
union all
select SchemeId = 10, RegionId , MessageId = 1 from dbo.Regions
union all
select SchemeId = 2, RegionId = 4, MessageId = 2
union all
select SchemeId , RegionId = 6, MessageId = 13 from dbo.Schemes;
In your procedure you could pull the messages like this:
select MessageId
from dbo.Messages_BrandProduct mbp
inner join dbo.[Messages] m on mbp.MessageId=m.MessageId
where mbp.BrandId = #BrandId and mbp.ProductId = #ProductId
union -- union all if you don't need to deduplicate messages
select MessageId
from dbo.Messages_SchemeRegion msr
inner join dbo.[Messages] m on msr.MessageId=m.MessageId
where msr.SchemeId = #SchemeId and msr.RegionId = #RegionId;
This should do it.
CREATE TABLE [dbo].[IDs](
[BrandID] [int] NOT NULL,
[ProductID] [int] NOT NULL,
[SchemeID] [int] NOT NULL,
[RegionID] [int] NOT NULL,
[MsgID] [int] NOT NULL
)
You can adjust the table and column names as needed. Cheers.

Select only one (NOT TOP) record base upon desired data priority

I have a sub-query that is part of a large query but really I think this problem is isolated to the subquery. If I am wrong however I will gladly post the entire thing.
I have records where a person may have 4 or 5 or 8 or 0 etc. entries. We want only one record but we have a preference. We'll take record B if record A isn't there etc.
Originally I was joining to the table
.....snip.....
LEFT JOIN [COMMUNICATION] Comm ON Peeps.PEOPLE_ID = Comm.PEOPLE_ID
and getting results such as
ID FIRST LAST ADDY BIZ CELL FAX HOME
21930 Person Name Addy 3237532500 NULL NULL NULL
21930 Person Name Addy NULL 3237910815 NULL NULL
21930 Person Name Addy NULL NULL 3235869055 NULL
21930 Person Name Addy NULL NULL NULL 3238660704
21930 Person Name Addy NULL NULL NULL NULL
In the communications table I really have 5 records so it is not a join issue.
Now I want only one row in this preference....
Home
Cell
Biz
Fax
So my first attempt was to do a subquery with TOP(1) but of course that only returns the top row of the table. I read on cte and am familiar with them but in this case I need to be able to join and not sure how you would 1. get the cte to order the records in the desired business priority and 2. how to join to it.
If you could just point my nose in the right direction or tell me what to study I will gladly do my own work.
Thanks
Without further information, this is what I came up to:
create table #temp_table (
[id] int,
[first] varchar(50),
[last] varchar(50),
[addy] varchar(50),
[biz] varchar(50) null,
[cell] varchar(50) null,
[fax] varchar(50) null,
[home] varchar(50) null
)
insert into #temp_table
select 21930, 'Person', 'Name', 'Addy', '3237532500', null, null, null union all
select 21930, 'Person', 'Name', 'Addy', null, '3237910815', null, null union all
select 21930, 'Person', 'Name', 'Addy', null, null, '3235869055', null union all
select 21930, 'Person', 'Name', 'Addy', null, null, null, '3238660704' union all
select 21930, 'Person', 'Name', 'Addy', null, null, null, null
;with ordered as(
select
*,
rn = row_number() over( partition by id
order by
case
when home is not null then 1
when cell is not null then 2
when biz is not null then 3
when fax is not null then 4
else 9999
end
)
from #temp_table
)
select
[id],
[first],
[last],
[addy],
[biz],
[cell],
[fax],
[home]
from ordered
where
rn = 1
drop table #temp_table

Copy Distinct Records Based on 3 Cols

I have loads of data in a table called Temp. This data consists of duplicates.
Not Entire rows but the same data in 3 columns. They are HouseNo,DateofYear,TimeOfDay.
I want to copy only the distinct rows from "Temp" into another table, "ThermData."
Basically what i want to do is copy all the distinct rows from Temp to ThermData where distinct(HouseNo,DateofYear,TimeOfDay). Something like that.
I know we can't do that. An alternative to how i can do that.
Do help me out. I have tried lots of things but haven't solved got it.
Sample Data. Values which are repeated are like....
I want to delete the duplicate row based on the values of HouseNo,DateofYear,TimeOfDay
HouseNo DateofYear TimeOfDay Count
102 10/1/2009 0:00:02 AM 2
102 10/1/2009 1:00:02 AM 2
102 10/1/2009 10:00:02 AM 2
Here is a Northwind example based on the Orders table.
There are duplicates based on the (EmployeeID , ShipCity , ShipCountry) columns.
If you only execute the code between these 2 lines:
/* Run everything below this line to show crux of the fix */
/* Run everything above this line to show crux of the fix */
you'll see how it works. Basically:
(1) You run a GROUP BY on the 3 columns of interest. (derived1Duplicates)
(2) Then you join back to the table using these 3 columns. (on ords.EmployeeID = derived1Duplicates.EmployeeID and ords.ShipCity = derived1Duplicates.ShipCity and ords.ShipCountry = derived1Duplicates.ShipCountry)
(3) Then for each group, you tag them with Cardinal numbers (1,2,3,4,etc) (using ROW_NUMBER())
(4) Then you keep the row in each group that has the cardinal number of "1". (where derived2DuplicatedEliminated.RowIDByGroupBy = 1)
Use Northwind
GO
declare #DestinationVariableTable table (
NotNeededButForFunRowIDByGroupBy int not null ,
NotNeededButForFunDuplicateCount int not null ,
[OrderID] [int] NOT NULL,
[CustomerID] [nchar](5) NULL,
[EmployeeID] [int] NULL,
[OrderDate] [datetime] NULL,
[RequiredDate] [datetime] NULL,
[ShippedDate] [datetime] NULL,
[ShipVia] [int] NULL,
[Freight] [money] NULL,
[ShipName] [nvarchar](40) NULL,
[ShipAddress] [nvarchar](60) NULL,
[ShipCity] [nvarchar](15) NULL,
[ShipRegion] [nvarchar](15) NULL,
[ShipPostalCode] [nvarchar](10) NULL,
[ShipCountry] [nvarchar](15) NULL
)
INSERT INTO #DestinationVariableTable (NotNeededButForFunRowIDByGroupBy , NotNeededButForFunDuplicateCount , OrderID,CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry )
Select RowIDByGroupBy , MyDuplicateCount , OrderID,CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry
From
(
/* Run everything below this line to show crux of the fix */
Select
RowIDByGroupBy = ROW_NUMBER() OVER(PARTITION BY ords.EmployeeID , ords.ShipCity , ords.ShipCountry ORDER BY ords.OrderID )
, derived1Duplicates.MyDuplicateCount
, ords.*
from
[dbo].[Orders] ords
join
(
select EmployeeID , ShipCity , ShipCountry , COUNT(*) as MyDuplicateCount from [dbo].[Orders] GROUP BY EmployeeID , ShipCity , ShipCountry /*HAVING COUNT(*) > 1*/
) as derived1Duplicates
on ords.EmployeeID = derived1Duplicates.EmployeeID and ords.ShipCity = derived1Duplicates.ShipCity and ords.ShipCountry = derived1Duplicates.ShipCountry
/* Run everything above this line to show crux of the fix */
)
as derived2DuplicatedEliminated
where derived2DuplicatedEliminated.RowIDByGroupBy = 1
select * from #DestinationVariableTable
emphasized text*emphasized text*emphasized text

Resources