INSERT INTO T_PROJECTGROUPSDATA (uploadID, fieldA,fieldB,......fieldN )
SELECT t.ID,p.fieldA,mg.fieldB,......mgc.fieldN
FROM T_Projects mp
INNER JOIN T_UPLOADS t mp.ID = t.project_savix_ID
INNER JOIN SG_Dynamic_Forms..v_projects p ON p.LegacyProjectId = mp.ID
INNER JOIN Savix_Service_Group..Groups mg ON mg.Grp_Project = p.ProjectID
INNER JOIN Savix_Service_Group..Group_Cycle mgc ON mgc.Gc_GroupID = mg.Grp_ID
INNER JOIN Savix_Service_Group..Group_Data mgd ON mgd.Gd_CycleID = mgc.Gc_ID
LEFT JOIN Savix_Service_Trainers..Trainers me ON me.Tr_ID = mgc.Gc_MonitoredBy
LEFT JOIN Savix_Service_Dictionaries..Dictionary mgt ON mgt.Dny_ID = me.Tr_Type
WHERE mp.SyncMode = 1
AND t.[STATUS] = 3 AND t.UPLOADFILENAME = 'Automatic upload from web MIS'
AND mg.Grp_IsDeleted = 0 AND mgd.Gd_IsDeleted != 1
UPDATE t SET
TOTALEXPENDITURES = CASE WHEN DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,mp.EndDate) != 0
THEN p.Cost_Until_Today*DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,dbo.fn_GetEndOfPeriod(t.Period_ID))/DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,mp.EndDate)/dbo.fn_RateAtDate(p.PROJECTCURRENCY_ID,dbo.fn_GetEndOfPeriod(t.Period_ID))
ELSE 0
END,
TotalExpendituresNative = CASE WHEN DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,mp.EndDate) != 0
THEN p.Cost_Until_Today*DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,dbo.fn_GetEndOfPeriod(t.Period_ID))/DATEDIFF(d,mp.PROJECTESTABLISHEDDATE,mp.EndDate)
ELSE 0
END
FROM T_UPLOADS t
JOIN T_Projects mp ON mp.ID = t.project_savix_ID AND mp.SyncMode = 1
WHERE t.[STATUS] = 3 AND t.UPLOADFILENAME = 'Automatic upload from web MIS'
यह समझाने के लिए कि मैं इसके साथ कैसे आया, यहाँ नीचे दिए गए कोड का एक संशोधित संस्करण है। मैं गारंटी नहीं दे सकता कि मुझे सब कुछ मिल गया है, मुझे कुछ धारणाएँ बनानी थीं। नमूना डेटा की कमी थी और सभी सैविक्स टेबल गायब हैं। यह सबसे अच्छा जवाब है जो मैं दी गई जानकारी के साथ आ सकता हूं और अपना समय 4 घंटे से कम निवेश तक सीमित कर सकता हूं। मैं और भी बहुत कुछ कर सकता था लेकिन आपको मुझे इंटरनेट की प्रसिद्धि से अधिक देना होगा।
--ALTER PROCEDURE [dbo].[proc_Upload] WITH RECOMPILE
--as
set NoCount on
DECLARE
@StartTime datetime,
@EndTime datetime,
@DataID uniqueidentifier,
@CollectionDate datetime,
@Status int,
@PeriodID int,
@EndDate datetime,
@GroupID uniqueidentifier,
@ProjectID INT,
@FAID uniqueidentifier,
@UploadID int ,
@Createdate datetime,
@MINIDprojects INT,
@MAXIDprojects INT,
@MINIDdatasets INT,
@MAXIDdatasets INT,
@MINIDperiods INT,
@MAXIDperiods INT
कर्सर को काम करना और परीक्षण करना मुश्किल है, इसलिए मैंने उन्हें (प्रोजेक्ट्स, प्रोजेक्ट्स1, डेटासेट और अवधि) एक पहचान वाली अस्थायी तालिकाओं के साथ बदल दिया और उनके माध्यम से लूप किया।
IF OBJECT_ID('tempdb..#projects') IS NOT NULL DROP TABLE #projects
IF OBJECT_ID('tempdb..#projects1') IS NOT NULL DROP TABLE #projects1
IF OBJECT_ID('tempdb..#datasets') IS NOT NULL DROP TABLE #datasets
IF OBJECT_ID('tempdb..#period') IS NOT NULL DROP TABLE #period
CREATE TABLE #projects
(
[ProjectID] [INT],
[Title] [varchar](255) ,
[currency] [int] ,
[Cost_Until_Today] [float] ,
[StartDate] [datetime] ,
[EndDate] [datetime] ,
[MisID] [uniqueidentifier] ,
[SystemStatus] [int] ,
[FacilitatingAgency] [uniqueidentifier] ,
[SyncMode] [int]
)
CREATE TABLE #projects1
(
ID INT IDENTITY(1,1),
[ProjectID] [INT],
[FacilitatingAgency] [uniqueidentifier]
)
CREATE TABLE #datasets
(
ID INT IDENTITY(1,1),
Gd_ID [uniqueidentifier],
Grp_ID [uniqueidentifier],
Gd_CollectionDate DATETIME,
Gd_IsDeleted BIT,
Gd_CreateDate DATETIME
)
CREATE TABLE #period
(
ID INT IDENTITY(1,1),
IDPeriod INT,
EndDate DATETIME
)
INSERT #projects ( [ProjectID], [Title], {currency], [Cost_Until_Today], [StartDate], [EndDate], [MisID], [SystemStatus], [FacilitatingAgency], [SyncMode] )
SELECT ID, PROJECTNAME, PROJECTCURRENCY_ID, Cost_Until_Today, PROJECTESTABLISHEDDATE, EndDate, MisID, 4, FacilitatingAgency, SyncMode
FROM [dbo].[T_PROJECTS] /*thsi is the source table where every projectIDs need to be processed*/
प्रोजेक्ट्स में T_Projects के सभी आईडी (प्रोजेक्ट आईडी) शामिल हैं, इस तालिका से उपयोग किए जाने वाले एकमात्र फ़ील्ड आईडी, प्रोजेक्टकुरेंसी, प्रोजेक्टस्टाल्डडेट (स्टार्टडेट), एंडडेट और सिंकमोड (होना चाहिए =1 होना चाहिए, हम बाद में देखेंगे)। हम सिस्टमस्टैटस को अनदेखा कर सकते हैं क्योंकि यह स्थिर है।
टेबल डैस्टैसेट्स को यहां गिराकर लोड किया जाता है। हम केवल Savix_Service_Group..Group_Data तालिका से gd_id की परवाह करते हैं, लेकिन फिर भी अन्य तालिकाओं में शामिल होने की आवश्यकता होती है यदि वे उन मानों को फ़िल्टर करते हैं जो हम नहीं चाहते हैं। अभिलेखों को सम्मिलित करते समय इस तर्क का उपयोग फिर से नीचे किया जाता है।
IF exists ( select * from dbo.sysobjects where id = object_id(N'[dbo].datasets]') and objectproperty(id, N'IsTable') = 1 ) DROP Table [dbo].datasets
SELECT mgd.Gd_ID, mg.Grp_ID, mgd.Gd_CollectionDate, mgd.Gd_IsDeleted, mgd.Gd_CreateDate, mg.Grp_Project, mg.Grp_IsDeleted , mg.Grp_Legacy_ID, p.LegacyProjectId
INTO datasets
FROM Savix_Service_Group..Group_Data mgd
INNER JOIN Savix_Service_Group..Group_Cycle mgc ON mgc.Gc_ID = mgd.Gd_CycleID
INNER JOIN Savix_Service_Group..Groups mg ON mg.Grp_ID = mgc.Gc_GroupID
inner join SG_Dynamic_Forms..v_projects p ON p.ProjectID = mg.Grp_Project
--DECLARE projects1 CURSOR LOCAL FOR Select distinct ProjectID, isnull([FacilitatingAgency], '00000000-0000-0000-0000-000000000000') from @projects P WHERE P.SystemStatus = 4 AND P.SyncMode = 1
--/*First cursor - fetch the cursor from ProjectaTable*/
--OPEN projects1
--FETCH NEXT FROM projects1 INTO @ProjectID, @FAID
--WHILE @@FETCH_STATUS = 0
यहां हम प्रोजेक्ट 1 में प्रोजेक्ट आईडी का एक अलग मूल्य डाल रहे हैं। अधिक डेटा के बिना, मेरी धारणा यह है कि आईडी T_projects तालिका में अलग है और इसलिए सिंकमोड =1 द्वारा फ़िल्टर करने के अलावा यह कदम कुछ हद तक अनावश्यक है। याद रखें कि सिस्टमस्टैटस स्थिर है और हमने इसे '4' मान के साथ पॉप्युलेट किया है, यह मानदंड को बिना किसी प्रभाव के हटाया जा सकता है।
INSERT INTO #projects1 ( ProjectID, FacilitatingAgency )
SELECT DISTINCT ProjectID, isnull([FacilitatingAgency], '00000000-0000-0000-0000-000000000000')
FROM #projects p
WHERE SystemStatus = 4 AND SyncMode = 1
SELECT @MINIDprojects = MIN(ID), @MAXIDprojects = MAX(ID) FROM #projects1
WHILE @MINIDprojects < @MAXIDprojects + 1
BEGIN
-- BEGIN TRY
-- BEGIN TRAN
SELECT @ProjectID = ProjectID, @FAID = FacilitatingAgency FROM #projects1 WHERE ID = @MINIDprojects
--DELETE FROM T_PROJECTGROUPSDATA WHERE T_PROJECTGROUPSDATA.UPLOAD_ID IN (SELECT ID FROM T_UPLOADS WHERE project_savix_ID = @ProjectID AND UPLOADFILENAME = 'Automatic upload from web MIS')
--DECLARE datasets CURSOR LOCAL FAST_FORWARD FOR SELECT Gd_ID, Grp_ID, Gd_CollectionDate, Gd_IsDeleted, Gd_CreateDate
-- FROM datasets
-- WHERE LegacyProjectId = @ProjectID AND Grp_IsDeleted = 0 AND Gd_IsDeleted != 1
-- /*Second cursor - this will get the 'collectionDate'field from datasetsTable for every project fetched in above cursor and also get @dataID which is used to insert value in to other table-T_PROJECTGROUPSDATA*/
--OPEN datasets
--FETCH NEXT FROM datasets INTO @DataID, @GroupID, @CollectionDate, @Status, @Createdate
--WHILE @@FETCH_STATUS = 0
यहां हम T_Project.ID और Savix_Service_Group..Groups.Grp_IsDeleted =0 और Savix_Service_Group..Group_Data.Gd_IsDeleted !=1
द्वारा फ़िल्टरिंग #डेटासेट में सम्मिलित करते हैं। INSERT INTO #datasets ( Gd_ID, Grp_ID, Gd_CollectionDate, Gd_IsDeleted, Gd_CreateDate )
SELECT Gd_ID, Grp_ID, Gd_CollectionDate, Gd_IsDeleted, Gd_CreateDate FROM datasets WHERE LegacyProjectId = @ProjectID AND Grp_IsDeleted = 0 AND Gd_IsDeleted != 1
SELECT @MINIDdatasets = MIN(ID), @MAXIDdatasets = MAX(ID) FROM #datasets
WHILE @MINIDdatasets < @MAXIDdatasets + 1
BEGIN
SELECT @DataID = Gd_ID, @GroupID = Grp_ID, @CollectionDate = Gd_CollectionDate, @Status = Gd_IsDeleted, @Createdate = Gd_CreateDate FROM #datasets WHERE ID = @MINIDdatasets
--DECLARE period CURSOR LOCAL FAST_FORWARD FOR SELECT ID, dbo.fn_GetEndOfPeriod(ID) FROM T_PERIODS
--/* dbo.fn_GetEndOfPeriod(ID) - this function will give the end of the date of that specifc quarter for any given date*/
-- WHERE DATEDIFF(dd,@CollectionDate,dbo.fn_GetEndOfPeriod(ID)) >= 0
-- ORDER BY [YEAR],[Quarter]
-- /*Third Cursor - this will process the records from another table called period with above fetched @collectionDate*/
--OPEN period
--FETCH NEXT FROM period INTO @PeriodID, @EndDate
--WHILE @@FETCH_STATUS = 0
यह शायद यहां कर्सर का सबसे खराब उपयोग है। हम सभी अवधियों को लोड करते हैं और उनके माध्यम से चक्र करते हैं। अंत में हम केवल उन अवधियों की परवाह करते हैं जो T_UPLOADS तालिका में हैं।
INSERT INTO #period ( IDPeriod, EndDate ) SELECT ID, dbo.fn_GetEndOfPeriod(ID) FROM T_PERIODS WHERE DATEDIFF(dd,@CollectionDate,dbo.fn_GetEndOfPeriod(ID)) >= 0
SELECT @MINIDperiods = MIN(ID), @MAXIDperiods = MAX(ID) FROM #period
WHILE @MINIDperiods < @MAXIDperiods + 1
BEGIN
--IF EXISTS (SELECT * FROM Savix_Service_Group..Group_Data mgd
-- INNER JOIN Savix_Service_Group..Group_Cycle mgc ON mgc.Gc_ID = mgd.Gd_CycleID
-- WHERE mgc.Gc_GroupID = @GroupID
-- AND DATEDIFF(dd,mgd.Gd_CollectionDate,@EndDate) >= 0
-- AND (mgd.Gd_CollectionDate > @CollectionDate )
-- AND mgd.Gd_IsDeleted != 1)
--BEGIN
-- BREAK
--END
यहां हम किसी भी अवधि को छोड़ देते हैं जहां UPLOADFILENAME !='वेब एमआईएस से स्वचालित अपलोड'
--IF EXISTS (SELECT ID FROM T_UPLOADS u WHERE u.project_savix_ID = @ProjectID AND u.PERIOD_ID = @PeriodID AND u.STATUS = 3 AND UPLOADFILENAME != 'Automatic upload from web MIS')
--BEGIN
-- FETCH NEXT FROM period INTO @PeriodID, @EndDate
-- CONTINUE
--END
इसे ध्यान में रखते हुए हम केवल यह ध्यान रखते हैं कि स्थिति =3 और UPLOADFILENAME ='वेब एमआईएस से स्वचालित अपलोड'
SET @UploadID = (SELECT ID FROM T_UPLOADS u WHERE u.project_savix_ID = @ProjectID AND u.PERIOD_ID = @PeriodID AND u.[STATUS] = 3 AND UPLOADFILENAME = 'Automatic upload from web MIS')
/*If T_uploads doesn't have appropirate period ID from cursor fetch then create a new entry in T_uploads with current projectID*/
IF @UploadID IS NOT NULL
BEGIN
--declare @Project_ID_Legacy int = ISNULL((select distinct PROJECT_ID from T_UPLOADS where project_savix_ID = @ProjectID),@ProjectID)
वे एक रिकॉर्ड बनाने के लिए दूसरी तालिका ( T_UPLOADFIRSTSTEP ) का उपयोग क्यों करते हैं, जहां वे केवल आईडी का उपयोग करते हैं और फिर T_Uploads रिकॉर्ड के निर्माण में उस आईडी का उपयोग करके रिकॉर्ड को हटाते हैं, यह मेरी समझ से परे है और मुझे भयानक कोडिंग प्रतीत होता है।
-- INSERT INTO T_UPLOADSFIRSTSTEP
-- (PROJECT_ID
-- --,UPLOADDATE
-- --,UPLOADFILENAME
-- --,UPLOADUSER_ID
-- --,CURRENTSTEP
-- ,[STATUS]
-- ,Project_ID_MIS)
-- SELECT ISNULL((select distinct PROJECT_ID from T_UPLOADS where project_savix_ID = @ProjectID),@ProjectID),
-- --GETDATE(),
-- --'Automatic upload from web MIS',
-- --2,
-- --2,
-- 0,
-- @ProjectID
T_UPLOADS में सम्मिलित करना हमेशा विफल रहेगा क्योंकि ऐसे क्षेत्र हैं जो शून्य नहीं हो सकते हैं जो सम्मिलित सूची में नहीं हैं और उनके पास कोई डिफ़ॉल्ट मान निर्दिष्ट नहीं है।
-- INSERT INTO T_UPLOADS ( ID, periodID, projectID,UPLOADDATE,UPLOADFILENAME,UPLOADUSER_ID )
-- SELECT uf.ID,
-- @PeriodID,
-- ISNULL((select distinct PROJECT_ID from T_UPLOADS where project_savix_ID = @ProjectID),@ProjectID),
-- GETDATE(),
-- 'Automatic upload from web MIS',
-- 2
-- FROM T_UPLOADSFIRSTSTEP uf
-- INNER JOIN #projects mp ON uf.Project_ID_MIS = mp.ProjectID
-- WHERE uf.Project_ID_MIS = @ProjectID AND uf.[STATUS] = 0
-- AND NOT EXISTS (SELECT * FROM T_UPLOADS u WHERE u.PROJECT_ID = uf.PROJECT_ID AND u.PERIOD_ID = @PeriodID AND u.[STATUS] = 3)
-- DELETE FROM T_UPLOADSFIRSTSTEP WHERE STATUS = 0 AND PROJECT_ID = ISNULL((select distinct PROJECT_ID from T_UPLOADS where project_savix_ID = @ProjectID),@ProjectID)
-- --SET @UploadID = (SELECT ID FROM T_UPLOADS u WHERE u.project_savix_ID = @ProjectID AND u.PERIOD_ID = @PeriodID AND u.[STATUS] = 3)
-- END
--ELSE
तो यहाँ असली तर्क है जो उन 3 कर्सर के अंदर किया जाता है। यह समझते हुए कि हमें अवधियों की परवाह नहीं है, तर्क उन सभी के माध्यम से घूमता है। हम केवल इस बात पर ध्यान देते हैं कि हमें कुछ मानदंड (स्थिति =3 और UPLOADFILENAME ='वेब एमआईएस से स्वचालित अपलोड') को फ़िल्टर करना है और उनके पास T_Project.ID मानदंड के साथ एक मिलान करने वाली T_Project.ID तालिका है। SyncMode =1
UPDATE t SET
TOTALEXPENDITURES = CASE WHEN DATEDIFF(d,mp.StartDate,mp.EndDate) != 0
THEN mp.Cost_Until_Today*DATEDIFF(d,mp.StartDate,dbo.fn_GetEndOfPeriod(t.Period_ID))/DATEDIFF(d,mp.StartDate,mp.EndDate)/dbo.fn_RateAtDate(mp.Currency,dbo.fn_GetEndOfPeriod(t.Period_ID))
ELSE 0
END,
TotalExpendituresNative = CASE WHEN DATEDIFF(d,mp.StartDate,mp.EndDate) != 0
THEN mp.Cost_Until_Today*DATEDIFF(d,mp.StartDate,dbo.fn_GetEndOfPeriod(t.Period_ID))/DATEDIFF(d,mp.StartDate,mp.EndDate)
ELSE 0
END
FROM T_UPLOADS t
JOIN #projects mp ON mp.ProjectID = t.project_savix_ID
WHERE 1=1 -- t.ID = @UploadID
--AND t.project_savix_ID = @ProjectID AND t.PERIOD_ID = @PeriodID
AND t.[STATUS] = 3 AND t.UPLOADFILENAME = 'Automatic upload from web MIS'
T_PROJECTGROUPDATA में डालने से #datasets से प्राप्त @dataid चर बनाने के लिए उपयोग किए गए तर्क को डुप्लिकेट किया गया है। जो हमारे द्वारा गिराए गए और ऊपर बनाए गए डेटासेट तालिका से लिया गया है।
INSERT INTO T_PROJECTGROUPSDATA (uploadID, fieldA,fieldB,......fieldN )
SELECT @UploadID,p.fieldA,mg.fieldB,......mgc.fieldN
FROM #projects mp
inner join SG_Dynamic_Forms..v_projects p ON p.LegacyProjectId = mp.projectID
inner join Savix_Service_Group..Groups mg ON mg.Grp_Project = p.ProjectID
INNER JOIN Savix_Service_Group..Group_Cycle mgc ON mgc.Gc_GroupID = mg.Grp_ID
INNER JOIN Savix_Service_Group..Group_Data mgd ON mgd.Gd_CycleID = mgc.Gc_ID
LEFT JOIN Savix_Service_Trainers..Trainers me ON me.Tr_ID = mgc.Gc_MonitoredBy
LEFT JOIN Savix_Service_Dictionaries..Dictionary mgt ON mgt.Dny_ID = me.Tr_Type
--left join v1_Report_UDF_Data_UploadToSavix udf on udf.DataID = mgd.Gd_ID
WHERE mgd.Gd_ID = @DataID
--FETCH NEXT FROM period INTO @PeriodID, @EndDate
SET @MINIDperiods = @MINIDperiods + 1
END
--CLOSE period
--DEALLOCATE period
--FETCH NEXT FROM datasets INTO @DataID, @GroupID, @CollectionDate, @Status, @Createdate
SET @MINIDdatasets = @MINIDdatasets + 1
END
--CLOSE datasets
--DEALLOCATE datasets
--COMMIT
--END TRY
--BEGIN CATCH
--SELECT ERROR_NUMBER(), ERROR_MESSAGE(),@PeriodID, @ProjectID, @UploadID,@DataID
--IF CURSOR_STATUS('global' , 'period') >= 0
--BEGIN
-- CLOSE period
-- DEALLOCATE uploadID
--END
--IF CURSOR_STATUS('global' , 'datasets') >= 0
--BEGIN
-- CLOSE datasets
-- DEALLOCATE datasets
--END
--IF @@TRANCOUNT > 0
-- ROLLBACK
--INSERT INTO error_catch_UploadtoSavix
--SELECT cast(ERROR_NUMBER() as nvarchar), ERROR_MESSAGE(),@PeriodID, @ProjectID, @UploadID,@DataID, getdate()
--END CATCH
SET @MINIDprojects = @MINIDprojects + 1
--FETCH NEXT FROM projects1 INTO @ProjectID, @FAID
END
--CLOSE projects1
--DEALLOCATE projects1
--SELECT 1 as success
ये लो। लगभग 300 लाइनों और 3 कर्सर को 30 लाइनों तक संघनित करना और कोई कर्सर नहीं।