how make grading system in sql server table creation - sql-server

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)

Related

accounting system data database Design

I have created accouting database as per my accounting knowledge.
I want to check Is that database is correct which i design for accounting system.
I have table called Mst_AccountGroup(Asset,Liabilities,Capital/Equity,Income & Expense data to create chart of account).
The database structure give below.
CREATE TABLE [dbo].[Mst_AccountGroup](
[AccountGrp_No] [int] NULL,
[AccountGrp_Name] [nvarchar](50) NULL,
[AccountGrp_Type] [nvarchar](50) NULL,
[AccountGrp_Increase] [nvarchar](50) NULL,
[AccountGrp_Decrease] [nvarchar](50) NULL,
[AccountGrp_Sign] [nvarchar](50) NULL,
[AccountGrp_SalesSign] [nvarchar](50) NULL,
[AccountGrp_ReceiptSign] [nvarchar](50) NULL,
[AccountGrp_PurchaseSign] [nvarchar](50) NULL,
[AccountGrp_PaymentSign] [nvarchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Mst_AccountCategory](
[AccountCat_No] [int] NULL,
[AccountCat_Name] [nvarchar](500) NULL,
[AccountCat_AccountGrpNo] [int] NULL,
[AccountCat_Sign] [nvarchar](50) NULL,
[AccountCat_SalesSign] [nvarchar](50) NULL,
[AccountCat_ReceiptSign] [nvarchar](50) NULL,
[AccountCat_PurchaseSign] [nvarchar](50) NULL,
[AccountCat_PaymentSign] [nvarchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Mst_AccountSubCategory](
[AccountSubCat_No] [int] NULL,
[AccountSubCat_AccountCatNo] [int] NULL,
[AccountSubCat_Name] [nvarchar](500) NULL,
[AccountSubCat_SalesSign] [nvarchar](50) NULL,
[AccountSubCat_ReceiptSign] [nvarchar](50) NULL,
[AccountSubCat_PurchaseSign] [nvarchar](50) NULL,
[AccountSubCat_PaymentSign] [nvarchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Trn_Ledger](
[Ledger_No] [int] NULL,
[Ledger_Name] [nvarchar](500) NULL,
[Ledger_AccountSubCatNo] [int] NULL,
[Ledger_VATNumber] [nvarchar](250) NULL,
[Ledger_CreditDays] [numeric](18, 0) NULL,
[Ledger_OpeningBalance] [numeric](18, 3) NULL,
[Ledger_BankName] [nvarchar](500) NULL,
[Ledger_BankAC] [nvarchar](500) NULL,
[Ledger_SwiftCode] [nvarchar](500) NULL,
[Ledger_BankAddress] [nvarchar](500) NULL,
[Ledger_Countory] [nvarchar](500) NULL,
[Ledger_VATPercent] [numeric](18, 3) NULL
) ON [PRIMARY]
GO
I have only one transaction table which include Sales,Receipt and Purchase, Payment and Journal Entries. Vouchers are seprating through [AccTran_VchType] field. Note that all the transaction are double entery.
Sales,Receipt and Purchase enteries, on those voucher user cannot make mistake to put the ledger on credit or debit side because from the chart of account once set then when select particular ledger then either it will be credit or debit system will tell the user.
CREATE TABLE [dbo].[Trn_AccountTransactionList](
[AccTran_No] [int] NULL,
[AccTran_Number] [nvarchar](50) NULL,
[AccTran_Date] [date] NULL,
[AccTran_Remark] [nvarchar](500) NULL,
[AccTran_VchType] [nvarchar](50) NULL,
[AccTran_RefNo] [nvarchar](250) NULL,
[AccTran_BillDate] [date] NULL,
[AccTran_Post] [numeric](18, 0) NULL,
[AccTran_Number2] [numeric](18, 0) NULL,
[AccTran_InvoiceNo] [numeric](18, 0) NULL,
[AccTran_PoNo] [numeric](18, 0) NULL,
[AccTran_PDC] [numeric](18, 0) NULL,
[Acc_TranLedgerNo] [numeric](18, 0) NULL,
[Acc_TranAmount] [numeric](18, 3) NULL,
[Acc_CompNo] [numeric](18, 0) NULL,
[Acc_Updatedby] [nvarchar](50) NULL,
[Acc_UpdatedDatetime] [datetime] NULL,
[Acc_BankDate] [date] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Trn_AccountTransaction](
[AccTran_No] [int] NULL,
[AccTran_No_N] [int] NULL,
[AccTran_AccountLedgerNo] [int] NULL,
[AccTran_AmountDR] [numeric](18, 3) NULL,
[AccTran_AmountCR] [numeric](18, 3) NULL,
) ON [PRIMARY]
GO
Trial balance query.
CREATE VIEW [dbo].[View_TrialBalance]
AS
SELECT TOP (100) PERCENT AccountCat_Name, AccountGrp_Name, DR, CR, AccountGrp_Type, AccountGrp_No, Balance, AccountSubCat_No, CASE WHEN AccountGrp_No IN (1,
5) THEN Balance ELSE 0 END AS TrialDebit, CASE WHEN AccountGrp_No IN (2, 3, 4) THEN Balance ELSE 0 END AS TrialCredit, AccountSubCat_Name, Ledger_No,
Ledger_Name, AccTran_Date, Comp_No, Comp_Name, Acc_CompNo, Comp_Add, Comp_Tel, Comp_Fax, Comp_Country
FROM dbo.View_Ledger
ORDER BY AccountSubCat_No
GO
View_P&LandBalanceSheet
CREATE VIEW [dbo].[View_P&LandBalanceSheet]
AS
SELECT TOP (100) PERCENT AccountCat_Name, AccountGrp_Name, DR, CR, AccountGrp_Type, Balance, TrialDebit, TrialCredit, AccountSubCat_No,
CASE WHEN AccountGrp_Type = 'P&L' THEN TrialDebit ELSE 0 END AS InDebit, CASE WHEN AccountGrp_Type = 'P&L' THEN TrialCredit ELSE 0 END AS InCredit,
CASE WHEN AccountGrp_Type = 'BS' THEN TrialDebit ELSE 0 END AS BSDebit, CASE WHEN AccountGrp_Type = 'BS' THEN TrialCredit ELSE 0 END AS BSCredit,
AccountSubCat_Name, Ledger_No, Ledger_Name, AccTran_Date, Comp_No, Comp_Name, Acc_CompNo, Comp_Add, Comp_Tel, Comp_Fax, Comp_Country,
YEAR(AccTran_Date) AS YRS
FROM dbo.View_TrialBalance
WHERE (NOT (AccountCat_Name IS NULL))
ORDER BY AccountSubCat_No
GO
Note that all other reports are coming correctly based on above Transaction table. I want to ask the database structure is perfect?

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

Finding recurring events that fall between two dates

I have been tasked with creating an events calendar for a website which will be backed by SQL Server. Using some of the information listed at: Calendar Recurring/Repeating Events - Best Storage Method I have created two tables in the database;
CREATE TABLE [Calendar].[Event](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[Details] [nvarchar](max) NOT NULL,
[EventType] [int] NOT NULL,
[Dismissable] [bit] NOT NULL DEFAULT ((1)),
[Created] [datetime2](7) NOT NULL DEFAULT (getdate()),
[CreatedBy] [uniqueidentifier] NOT NULL,
[LastEdited] [datetime2](7) NOT NULL DEFAULT (getdate()),
[EditedBy] [uniqueidentifier] NOT NULL
)
CREATE TABLE [Calendar].[EventSchedule](
[Id] [int] IDENTITY(1,1) NOT NULL,
[EventId] [int] NOT NULL,
[StartDate] [datetime2](7) NOT NULL,
[EndDate] [datetime2](7) NULL,
[IntervalDays] [int] NULL,
[IntervalWeeks] [int] NULL,
[IntervalMonths] [int] NULL,
[IntervalYears] [int] NULL,
[WeekDayNumber] [int] NULL,
[MonthWeekNumber] [int] NULL,
[YearMonthNumber] [int] NULL
)
I am now attempting to write a stored procedure to capture all events (singular and recurring) that fall between a date range, but cannot get my head around a catch all solution that doesn't involve generating temporary tables or cursors.
My current roadblock is the events that recur every n days. So far I have the following:
CREATE PROCEDURE Calendar.GetEventsForDateRange
#StartDateRange DATETIME2
#EndDateRange DATETIME2
AS
BEGIN
SELECT * --for brevity
FROM Calendar.EventSchedule
WHERE (StartDate <= #EndDateRange
AND DATEDIFF(DAY, StartDate, #EndDateRange) / IntervalDays >= 1)
OR (StartDate >= #StartDateRange AND StartDate <= #EndDateRange)
END
I have an event where StartDate = 2017-07-02 and IntervalDays = 7. If I pass a #StartDateRange = 2017-07-03 and #EndDateRange = 2017-07-09 the event is correctly returned. If I then change the #StartDateRange = 2017-07-13 and #EndDateRange = 2017-07-15 the event is still returned, where its next occurrence should be 2017-07-16.
How would I alter/amend my current stored procedure to return events that will only occur within a date range?
Any help on this would be greatly appreciated.

Update Item from same table where values are null

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;

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