Update Item from same table where values are null - sql-server

I have a table Member where their are duplicate entries and I want to remove one of them, but 1 of the entry has some columns updated and another has some other.
So What I want to do is update but the columns where values exist in 1 and null or empty in another so that both the rows become completely identical and I do not loose any data out of it.
Table Structure:
CREATE TABLE [dbo].[membermobilenumberisnull](
[TransId] [bigint] NOT NULL,
[member_id] [int] NOT NULL,
[gendertype] [int] NULL,
[relationship_rs_code] [nvarchar](2) NULL,
[ration_card_id] [int] NOT NULL,
[uid] [nvarchar](16) NULL,
[member_dob] [datetime] NULL,
[member_name_en] [nvarchar](150) NULL,
[mother_name_en] [nvarchar](150) NULL,
[father_name_en] [nvarchar](150) NULL,
[member_age] [smallint] NULL,
[nationality] [nvarchar](150) NULL,
[MobileNumber] [nvarchar](20) NULL,
[IsUpdated] [bigint] NULL,
[UpdationDate] [datetime] NULL,
[IsDeleted] [bigint] NULL,
[DeletionDate] [datetime] NULL,
[CreationDate] [datetime] NULL,
[UpdatedBy] [nvarchar](250) NULL,
[DeletedBy] [nvarchar](250) NULL,
[MobileNumber1] [nvarchar](20) NULL,
[MobileFlag] [nvarchar](250) NULL
) ON [PRIMARY]
GO
Sample Data
TransId member_dob member_name_en member_age nationality MobileNumber UpdationDate CreationDate
252238402 12-09-1985 PUSHPINDER SINGH 31 IND NULL 30-07-2016
252238403 12-09-1985 PUSHPINDER SINGH 31 IND 8626934377 NULL 30-07-2016
260846102 03-06-1984 VUDDHI DEVI 32 IND 9459209701 19-10-2016 14-08-2016
260846105 03-06-1984 VUDDHI DEVI 32 IND NULL 14-08-2016
Expected Result:
TransId member_dob member_name_en member_age nationality MobileNumber UpdationDate CreationDate
252238402 12-09-1985 PUSHPINDER SINGH 31 IND 8626934377 NULL 30-07-2016
252238403 12-09-1985 PUSHPINDER SINGH 31 IND 8626934377 NULL 30-07-2016
260846102 03-06-1984 VUDDHI DEVI 32 IND 9459209701 19-10-2016 14-08-2016
260846105 03-06-1984 VUDDHI DEVI 32 IND 9459209701 19-10-2016 14-08-2016
Thanks in advance
Example attached:

Assume your combined PK is member_dob,member_name_en,member_age
UPDATE M1
SET M1.MobileNumber = ISNULL(NULLIF(M1.MobileNumber,''),M2.MobileNumber)
,M1.UpdationDate = ISNULL(M1.UpdationDate,M2.UpdationDate)
FROM Member AS M1
INNER JOIN Member AS M2 ON M1.TransId <> M2.TransId
AND M1.member_dob = M2.member_dob
AND M1.member_name_en = M2.member_name_en
AND M1.member_age = M2.member_age

Try this
WITH t2 AS (
SELECT member_dob, member_name_en, member_age, nationality, MobileNumber
FROM <<table>>
WHERE MobileNumber IS NOT NULL
)
UPDATE t1
SET MobileNumber = t2.MobileNumber
FROM <<table>> t1 JOIN t2
ON t1.member_dob = t2.member_dob
AND t1.member_name_en = t2.member_name_en
AND t1.member_age = t2.member_age
AND t2.nationality = t2.nationality
WHERE t1.MobileNumber IS NULL

It seems you want to look at a member_name_en and take a value from whichever of its records, preferring non-null over null. Then simply aggregate and use MIN or MAX to pick such value.
update m
set member_dob = src.max_member_dob
, member_age = src.max_member_age
, nationality = src.max_nationality
etc.
from membermobilenumberisnull m
(
select
member_name_en,
max(member_dob) as max_member_dob,
max(member_age) as max_member_age,
max(nationality) as max_nationality,
etc.
from membermobilenumberisnull
group by member_name_en
) src on src.member_name_en = m.member_name_en;

Related

Fill a table from CSV file with stored procedure

I want to import data from this SQL table:
CREATE TABLE [dbo].[TempExchangeRates](
[currency (Libellés)] [nvarchar](255) NULL,
[Currency Code] [nvarchar](255) NULL,
[2019-03] [float] NULL,
[2019-04] [float] NULL,
[2019-05] [float] NULL,
[2019-06] [float] NULL,
[2019-07] [float] NULL,
[2019-08] [float] NULL,
[2019-09] [float] NULL,
[2019-10] [float] NULL,
[2019-11] [float] NULL,
[2019-12] [float] NULL,
[2020-01] [float] NULL,
[2020-02] [float] NULL
)
With sample data:
To this one:
CREATE TABLE [dbo].[ExchangeRates]
(
[IdExchangeRate] [uniqueidentifier] NOT NULL,
[ExchangeRateCode] [nvarchar](10) NULL,
[ExchangeRatePeriodStartDate] [datetime] NULL,
[ExchangeRatePeriodEndDate] [datetime] NULL,
[ExchangeRateValue] [decimal](20, 5) NULL,
[CurrencyCode] [nvarchar](10) NULL,
)
Now I want to call a stored procedure to get fill the real table like that:
I start with stored procedure like that but I'm not sure how I could do that
------------------------- 3. Declare StartDateTable --------------------
DECLARE #StartDateExchangeRate TABLE
(
rowid INT IDENTITY(1,1) NOT NULL,
value float,
startDate date
)
-- Insert Into #StartDateExchangeRate(value, startDate)
--This finds the start dates by finding unmatched values
--SELECT id,value
-- from ExchangeRates
------------------------- 2. Declare EndDateTable --------------------
DECLARE #EndDateExchangeRate TABLE
(
EndDate date
)
Insert Into #ENdDateExchangeRate(EndDate)
--This finds the start dates by finding unmatched values
SELECT EOMONTH(startdate)
FROM #StartDateExchangeRate As ER1
-------------------------3. Join NotYet--------------------------
This question is lacking in details
Assuming the TempExchangeRates columns will vary as time goes on, here is a option that will dynamically UNPIVOT the data so it can be inserted into your final structure.
Example (or dbFiddle)
Select ExchangeRateCode = A.[Currency Code]
,ExchangeRatePeriodStartDate = period
,ExchangeRatePeriodEndDate = EOMonth(period)
,ExchangeRateValue = B.Value
,CurrencyCode = replace(upper(A.[currency (Libellés)]),' ','')
,CreatedBy = 'SomeString'
,CreatededAt = getdate()
From [TempExchangeRates] A
Cross Apply ( Select period = try_convert(date,[Key]+'-01')
,Value = try_convert(float,value)
From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ))
Where [Key] not in ('currency (Libellés)','Currency Code')
) B
Returns

how make grading system in sql server table creation

I have a table of student averages of four college year and field for find the average of four year degrees and the final field is for grading system.
My question: I want to make grade field value based on final_avg column. How can I achieve this?
For example if final_avg < 50 then grade = failed, if final_avg >= 50 and final_avg < 60 then grade = satisfactory and so on.
This is my table:
CREATE TABLE averages_tbl(
[avg_id] [int] IDENTITY(1,1) NOT NULL,
[Student_ID] [int] NOT NULL,
[f_s_avg] [float] NULL,
[s_s_avg] [float] NULL,
[t_s_avg] [float] NULL,
[fu_s_avg] [float] NULL,
[final_avg] AS ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]),
[grade] [nvarchar](20) NULL,
)
Simple way:
CREATE TABLE averages_tbl(
[avg_id] [int] IDENTITY(1,1) NOT NULL,
[Student_ID] [int] NOT NULL,
[f_s_avg] [float] NULL,
[s_s_avg] [float] NULL,
[t_s_avg] [float] NULL,
[fu_s_avg] [float] NULL,
[final_avg] AS ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]),
[grade] AS (CASE WHEN ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]) < 50 THEN 'Failed'
WHEN ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]) between 50 and 59 THEN 'Satisfied'
ELSE 'Whatever' END)
)
Or with ALTER TABLE:
ALTER TABLE averages_tbl DROP COLUMN [grade]
ALTER TABLE averages_tbl ADD [grade] AS (
CASE WHEN ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]) < 50 THEN 'Failed'
WHEN ((([f_s_avg]+[s_s_avg])+[t_s_avg])+[fu_s_avg]) between 50 and 59 THEN 'Satisfied'
ELSE 'Passed' END)

sql join not showing some records

I'm trying to find all customers who have placed an order but there isn't a callback after their last order date.
My current query:
SELECT dbo.[Order].CustomerId, MAX(OrderDate) AS OrderDate, NextCallbackDate, UserName
FROM dbo.[Order]
LEFT OUTER JOIN (SELECT MAX(CallbackDate) NextCallbackDate, CustomerID
FROM AccountCallbacks
GROUP By CustomerId
) callbacks ON callbacks.CustomerID = dbo.[Order].CustomerID
LEFT OUTER JOIN dbo.aspnet_Users users ON dbo.[Order].UserID = users.UserId
WHERE (PaymentTypeID IN (2, 3, 4, 6, 8))
AND OrderDate >= NextCallbackDate
GROUP BY dbo.[Order].CustomerID, dbo.[Order].OrderDate,callbacks.NextCallbackDate, UserName
ORDER BY dbo.[Order].CustomerID
Tables:
AccountCallBacks:
[CallbackID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [uniqueidentifier] NOT NULL,
[CustomerID] [int] NOT NULL,
[Created] [datetime] NOT NULL,
[CallbackDate] [date] NOT NULL,
[Enabled] [bit] NOT NULL,
[CallbackTimeID] [int] NULL,
[GaryCust] [bit] NULL,
[NotInterestedReasonID] [int] NULL
Order Table:
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[CustomerID] [int] NULL,
[UserID] [uniqueidentifier] NULL,
[OrderDate] [datetime] NOT NULL,
[PaymentTypeID] [int] NULL,
[PaymentStatusID] [int] NOT NULL,
[PaymentDate] [datetime] NULL,
[TransactionRef] [varchar](50) NULL
And the aspnet_Users table is the usual .net membership users table
EDIT:
Apologies! I never actual said what was wrong! My query doesn't give me what I'm expecting one of the rows of data for a particular CustomerID isn't in the result set. And no, there should always be at least one AccountCallbacks.CallbackDate for every CustomerID as I'm joining on the dbo.[Order] table and they wouldn't be in there without first ever being in the AccountCallbacks table.
Feel free to ask any other info, help is greatly appreciated.

Select distinct from a table foreach value from another

I have a view that gets the status for each category for each venue.
I need to display all of the above, but only the latest in the status for each category for each venue.
A general idea could be, for each item in a shop, there is a status. So for the cucumbers, letters, and tomatoes in shop A, the status would be good good bad respectively. Same for shop B, C etc. Now these statuses can be updated at any time - but only the latest update should be displayed.
I have tried to create a view such as the following:
SELECT
dbo.vwVenues.HospitalID
, dbo.vwVenues.Hospital AS hospitalName
, dbo.tblVenueStatus.id AS statusId
, dbo.tblVenueStatusName.statusName
, dbo.tblVenueStatusCategories.categoryName
, dbo.tblVenueStatus.dateAdded AS statusDateAdded
, dbo.tblVenueStatus.loggedBy AS statusLoggedBy
, dbo.tblVenueStatusNotes.noteContent
, dbo.tblVenueStatusNotes.dateAdded AS noteDateAdded
, dbo.tblVenueStatusNotes.removed AS noteRemoved
, dbo.tblVenueStatus.resolved AS statusResolved
, dbo.tblVenueStatus.resolveDate AS statusResolveDate
, dbo.tblVenueStatus.removed AS statusRemoved
, dbo.tblVenueStatus.dateRemoved AS statusRemovedDate
, dbo.tblVenueStatus.categoryId
FROM
dbo.tblVenueStatusName
RIGHT OUTER JOIN dbo.tblVenueStatusNotes
RIGHT OUTER JOIN dbo.tblVenueStatus
ON dbo.tblVenueStatusNotes.id = dbo.tblVenueStatus.noteId
LEFT OUTER JOIN dbo.tblVenueStatusCategories
ON dbo.tblVenueStatus.categoryId = dbo.tblVenueStatusCategories.id
ON dbo.tblVenueStatusName.id = dbo.tblVenueStatus.statusNameId
FULL OUTER JOIN dbo.vwVenues
ON dbo.tblVenueStatus.venuId = dbo.vwVenues.HospitalID
I get all the venues, but I get all the statuses for each category, instead of just the latest. Even trying to phrase the question right was hard - so my current search yeilded nothing.
Could anyone please help?
Edit
CREATE TABLE [dbo].[tblVenueStatus](
[id] [int] IDENTITY(1,1) NOT NULL,
[statusNameId] [int] NOT NULL,
[venuId] [int] NOT NULL,
[categoryId] [int] NOT NULL,
[loggedBy] [nvarchar](50) NOT NULL,
[noteId] [int] NOT NULL,
[dateAdded] [datetime] NOT NULL,
[resolved] [tinyint] NOT NULL,
[resolveDate] [datetime] NULL,
[removed] [tinyint] NOT NULL,
[dateRemoved] [datetime] NULL,
CONSTRAINT [PK_tblSiteVenuStatus] PRIMARY KEY CLUSTERED
CREATE TABLE [dbo].[tblVenueStatusCategories](
[id] [int] IDENTITY(1,1) NOT NULL,
[categoryName] [nvarchar](50) NOT NULL,
[categoryDescription] [nvarchar](150) NULL,
CONSTRAINT [PK_tblVenueStatusCategories] PRIMARY KEY CLUSTERED
CREATE TABLE [dbo].[tblVenueStatusName](
[id] [int] IDENTITY(1,1) NOT NULL,
[statusName] [nvarchar](50) NOT NULL,
[statusDescription] [nchar](150) NULL,
CONSTRAINT [PK_tblVenuStatusName] PRIMARY KEY CLUSTERED
CREATE TABLE [dbo].[tblVenueStatusNotes](
[id] [int] IDENTITY(1,1) NOT NULL,
[noteContent] [nvarchar](500) NULL,
[dateAdded] [datetime] NOT NULL,
[removed] [tinyint] NOT NULL,
[dateRemoved] [datetime] NULL,
CONSTRAINT [PK_tblVenueStatusNotes] PRIMARY KEY CLUSTERED
Desired Output will be:
Venu Name | Category 1 Status | Category 2 Status
Try something like this. It's largely sumerised because of what you said you needed to see in your sample. Try this and let me know if it helps. You can add other columns you need here, It is taking the latest status in each category for each hospital, and showing all hospitals and categories in a easily readable grid.
SELECT * FROM
(
SELECT VwV.HospitalID, vwV.Hospital, ISNULL(vStatusName.statusName, '') AS statusName, vStatusCategories.categoryName
FROM
(
SELECT topStatus.HospitalID, topStatus.categoryId, sta2.id
FROM
(
SELECT HospitalID, categoryId, MAX(sta.dateAdded) AS DateAdded
FROM vwVenues
INNER JOIN tblVenueStatus sta ON sta.venuId = dbo.vwVenues.HospitalID
GROUP BY HospitalID, categoryId
) topStatus
INNER JOIN tblVenueStatus sta2 ON sta2.dateAdded = topStatus.DateAdded AND sta2.venuId = topStatus.HospitalID) Statuss
FULL OUTER JOIN vwVenues vwV ON vwV.HospitalID = Statuss.HospitalID
LEFT OUTER JOIN tblVenueStatus vStatus ON vStatus.id = Statuss.id
LEFT OUTER JOIN tblVenueStatusName vStatusName ON vStatusName.id = vStatus.statusNameId
LEFT OUTER JOIN tblVenueStatusCategories vStatusCategories ON vStatus.categoryId = vStatusCategories.id AND vStatusName.id = vStatus.statusNameId
LEFT OUTER JOIN tblVenueStatusNotes vStatusNotes ON vStatusNotes.id = vStatus.noteId
) AS s
PIVOT (MIN(StatusName)
FOR [CategoryName] IN ([Category1],[Category2])) AS PTbl

A typical performance case of SQL Optimization

I have an engineering practice of SQL Optimization problem, which I think is a typical case ,and will help a lot of guys.
SQL SERVER 2005,
Firstly, create the main table. This is a person info table.
CREATE TABLE [dbo].[OLAPAgentDim](
[RoleID] [varchar](50) NULL CONSTRAINT [DF_OLAPAgentDim_RoleID] DEFAULT ((1)),
[OLAPKey] [bigint] IDENTITY(1,1) NOT NULL,
[FatherKey] [bigint] NULL,
[FatherKeyValue] [nvarchar](100) NULL,
[System] [varchar](6) NULL,
[Level] [int] NULL,
[IfLeaf] [real] NULL,
[IfDel] [real] NULL CONSTRAINT [DF_OLAPAgentDim_IfDel] DEFAULT ((0)),
[SourceKey] [varchar](50) NULL,
[MainDemoName] [nvarchar](100) NULL,
[FastCode] [varchar](50) NULL,
[TagValue] [varchar](50) NULL,
[Script] [nvarchar](max) NULL,
[Birthday] [datetime] NULL,
[EarlyStartTime] [datetime] NULL,
[StartTime] [datetime] NULL,
[EndTime] [datetime] NULL,
[EditTime] [datetime] NULL,
[BecomesTime] [datetime] NULL,
[ContractTime] [datetime] NULL,
[ContractEndTime] [datetime] NULL,
[XMLIcon] [nvarchar](max) NULL,
[PassKey] [varchar](50) NULL CONSTRAINT [DF_OLAPAgentDim_PassKey] DEFAULT ('N3pkY3RHaeZXA9mGJdfm8A=='),
[Address] [nvarchar](100) NULL,
[HomeTel] [varchar](50) NULL,
[Mobile] [varchar](50) NULL,
[Email] [varchar](100) NULL,
[IDCard] [varchar](50) NULL,
[IDSecu] [varchar](50) NULL,
[IDEndowment] [varchar](50) NULL,
[IDAccumulation] [varchar](50) NULL,
[ContactPerson] [nvarchar](100) NULL,
[ContactPersonTel] [varchar](50) NULL,
[Others1] [varchar](50) NULL,
[SexKey] [varchar](2) NULL CONSTRAINT [DF_OLAPAgentDim_SexKey] DEFAULT ((1)),
[SexKeyValue] [nvarchar](100) NULL,
[MarrageKey] [varchar](2) NULL CONSTRAINT [DF_OLAPAgentDim_MarrageKey] DEFAULT ((1)),
[MarrageKeyValue] [nvarchar](100) NULL,
[Nation] [nvarchar](50) NULL,
[Race] [nvarchar](50) NULL,
[PartyMemberKey] [varchar](2) NULL CONSTRAINT [DF_OLAPAgentDim_PartyMemberKey] DEFAULT ((1)),
[PartyMemberKeyValue] [nvarchar](100) NULL,
[RegionKey] [bigint] NULL CONSTRAINT [DF_OLAPAgentDim_RegionKey] DEFAULT ((1)),
[RegionKeyValue] [nvarchar](100) NULL,
[LeaveResonKey] [bigint] NULL CONSTRAINT [DF_OLAPAgentDim_LeaveResonKey] DEFAULT ((1)),
[LeaveResonKeyValue] [nvarchar](100) NULL,
[RoleStr] [varchar](max) NULL,
[RoleStrValue] [nvarchar](max) NULL,
[LeaderKey] [bigint] NULL CONSTRAINT [DF_OLAPAgentDim_LeaderKey] DEFAULT ((1)),
[LeaderKeyValue] [nvarchar](100) NULL,
[FastCode2] [varchar](50) NULL,
[FastCode3] [varchar](50) NULL,
[FastCode4] [varchar](50) NULL,
[FastCode5] [varchar](50) NULL,
[OtherAddress] [nvarchar](100) NULL,
[ShowOrder] [int] NULL,
[RaceKey] [bigint] NULL DEFAULT ((1)),
[RaceKeyValue] [nvarchar](100) NULL,
[DepartLevelKey] [bigint] NULL DEFAULT ((1)),
[DepartLevelKeyValue] [nvarchar](100) NULL,
[forumname] [nvarchar](100) NULL,
[IfCloseKey] [bigint] NULL DEFAULT ((1)),
[IfCloseKeyValue] [nvarchar](100) NULL,
[InsureStartTime] [datetime] NULL,
[AccumulationStartTime] [datetime] NULL,
[Rate] [varchar](50) NULL,
[DirectLeaderKey] [bigint] NULL CONSTRAINT [DF_OLAPAgentDim_DirectLeaderKey] DEFAULT ((1)),
[DirectLeaderAttriKey] [bigint] NULL CONSTRAINT [DF_OLAPAgentDim_DirectLeaderAttriKey] DEFAULT ((1)),
[DirectLeaderKeyValue] [nvarchar](100) NULL,
[DirectLeaderSourceKey] [varchar](50) NULL,
[DirectLeaderPartName] [nvarchar](100) NULL,
[DirectLeaderPositionName] [nvarchar](100) NULL,
[NOTSync] [int] NULL,
[FatherPath] [nvarchar](max) NULL,
[SaleDiscount] [real] NULL,
CONSTRAINT [PK_OLAPAgent Dim] PRIMARY KEY CLUSTERED
(
[OLAPKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Secondly, insert abount 10,000 record into the table. I think 10,000 record is not a very big number to SQL SERVER. You can see this is a father and children dimention table in fact. The records with ifleaf=0 means the person's department structure node, the records with ifleaf=1 means the person. You can define father-children relationship using FahterKey column. For Example:
OLAPKey IfLeaf FatherKey DepartLevelKey MainDemoName
2 0 0 1 IBM Company
3 0 2 2 Sales Depart
4 0 2 2 Service Depart
5 0 3 3 Sales Team1
6 1 5 NULL John Smith
7 1 4 NULL Mary
......
DepartLevelKey Column means the depart node's level.
So in this table, we can save the whole HR tree info.
Thirdly, we see the problem SQL:
create table #t
(
TableID int IDENTITY(1,1),
OLAPKey bigint,
MainDemoName nvarchar(max)
)
declare #t4 table
(
TableID int IDENTITY(1,1),
MainDemoName nvarchar(max),
OLAPKeystr varchar(100)
)
declare #agentkey bigint
set #agentkey ='2'
--Part A
--DepartLevelKey=2, to get #agentkey node's all level=2 department
;WITH Result AS(
SELECT OLAPKey,DepartLevelKey,maindemoname FROM OLAPAgentDim WHERE OLAPKey =#agentkey
UNION ALL
SELECT a.OLAPKey,a.DepartLevelKey,a.maindemoname FROM OLAPAgentDim AS a,Result AS b WHERE a.FatherKey = b.OLAPKey
)
insert #t select OLAPKey,maindemoname from Result where DepartLevelKey=4
--Part B
;with One as
(
select *,convert(varchar(50),OLAPKey) as Re from #t
)
insert #t4 select maindemoname,stuff((select ','+Re from One where One.maindemoname=#t.maindemoname for xml path('')),1,1,'') as Two
from #t
group by maindemoname
drop table #t
The SQL above is divided into Part A and Part B.
Part A SQL get all the childrens below a root node(and filtered those belong to the specified DepartLevelKey). For example, to get all persons in Sales Department's child-department with level=3.
Part B SQL change the rows to column, For example:
Change:
TableID OLAPKey MainDemoName
1 6 Sales Team1
2 10 Sales Team1
3 12 Sales Team1
to:
TableID MainDemoName OLAPKeystr
1 Sales Team1 6,10,12
Thus we get each goal department's persons, for further processing(omited here).
The Problem:
The Part A is very slow, cost about 5 minutes. The Part B is slow too.
I wonder how to optimize it basing the table struc existed.
yours,
Ivan
Try:
(i) Adding this index to OLAPAgentDim:
create index IX_OLAPAgentDim_FatherKey on OLAPAgentDim (FatherKey) include (DepartLevelKey, MainDemoName)
(ii) Changing MainDemoName in #t from nvarchar(max) to nvarchar(100). This matches the column definition in OLAPAgentDim.
(iii) Between Part A and Part B, i.e. after Part A and before Part B, adding this index to #t:
create clustered index IX on #t (MainDemoName)

Resources