Insert a constant value to table in stored procedure - sql

I have the following stored procedure:
DECLARE #BeginDate1 datetime, #EndDate1 datetime
set #BeginDate1 = '04-01-2012'
set #EndDate1 = '03-31-2013'
BEGIN
INSERT INTO MTBUR_Type_Stage
SELECT
R.Type, [Hours],
LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartName(R.ACSS_PartID), 1) - 1) AS 'Part No',
Count(s.status) AS NumberUnscheduled,
([Hours]/Count(s.status)) AS MTBUR
FROM
Repair R
INNER JOIN
Conversion C ON (R.Performed = C.Performed)
AND (R.Confirmed = C.Confirmed)
INNER JOIN
Status S ON C.StatusID = S.StatusID
INNER JOIN
#MTBUR_Hrs_Temp TEMP ON LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartName(R.PartID), 1) - 1) = TEMP.productNo
AND R.Type = TEMP.Type
WHERE
(R.Received BETWEEN #BeginDate1 AND #EndDate1)
AND (S.Status = 'UNSCHEDULED')
GROUP BY
LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartNaame(R.PartID), 1) - 1), [Hours], R.Type
ORDER BY
R.Type,
LEFT(dbo.fn_GetPartName(R.ACSS_PartID),CHARINDEX('-',dbo.fn_GetPartID(R.PartID), 1) - 1) ASC
DROP TABLE #MTBUR_Hrs_Temp
END
The table being inserted to (MTBUR_Type_Stage) has columns named EndingDate and EndingQuarter. EndingDate needs to have the same date (constant) which is equal to #EndDate and EndingQuarter needs to have a constant value of 1
How can I script this in my stored procedure so that ALL rows are populated with these constants in the relevant columns in MTBUR_Type_Stage are populated with these constants?
The following is the DDL for the table I am inserting into:
CREATE TABLE [dbo].[MTBUR_ByType_StageTbl]
(
[Type] [nvarchar](25) NULL,
[Hours] [float] NULL,
[Part No] [varchar](15) NULL,
[UnscheduledRemovals] [int] NULL,
[MTBUR] [float] NULL,
[EndingDate] [datetime] NULL,
[EndingQuarter] [int] NULL
) ON [PRIMARY]

As simple as this:
insert MTBUR_Type_Stage(EndingDate,EndingQuarter)
values (#EndDate,1)
;
or this
insert MTBUR_Type_Stage(EndingDate,EndingQuarter)
select #EndDate,1
Expanded for more fields:
insert MTBUR_Type_Stage(
[Type],
[Hours],
[Part No],
[UnscheduledRemovals],
[MTBUR],
[EndingDate],
[EndingQuarter] [int] NULL
)
select
'x',1.00,'part 1', 0, 2.34,
#EndDate,1

Related

Update multiple latest record on table using loop

CREATE TABLE [dbo].[masterTable]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[CID] [int] NOT NULL,
[PID] [int] NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[State] [nchar](20) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
INSERT INTO [dbo].[masterTable]
([CID]
,[PID]
,[Description]
,[CreatedOn]
)
VALUES
(189
,186
,'FC1_189'
,GETUTCDATE()),
(189
,186
,'FC2_189'
,DATEADD(D, +1, GETUTCDATE())),
(190
,186
,'FC1_190'
,DATEADD(d, +2, GETUTCDATE())),
(190
,186
,'FC2_190'
,DATEADD(d, +3, GETUTCDATE())),
(191
,186
,'FC1_191'
,DATEADD(d, +4, GETUTCDATE())),
(191
,186
,'FC2_191'
,DATEADD(d, +5, GETUTCDATE()))
I have a table with 6 records I am trying to update the latest created record based on CID and PID data with the state 'Latest data' and other old created on should update state with 'old data' I tried this but for old created on data not working. check the below query.
Explanation: I currently have 6 records based on CID and PID data.
FC2_189 row is the latest record based on createdOn column so, for this row state column should update with 'latest data' and the other record FC1_189 are old records based on created on date, so compared to FC2_189 row this record is old data based on createdon column so state column should update with 'old data'.
same should happen with FC2_190,FC1_190 and FC2_191,FC1_191 data
SELECT Description,
STATE,
CreatedOn,
PID,
CID,
ROW_NUMBER() OVER (
PARTITION BY ContractID ORDER BY CreatedOn DESC
) contractRN
INTO #ControlTable
FROM masterTable
DECLARE #i INT = 1
DECLARE #count INT
SELECT #count = Count(*)
FROM #ControlTable
WHILE #i <= #count
BEGIN
UPDATE masterTable SET State =
CASE WHEN CreatedOn = (SELECT MAX(CreatedOn) FROM masterTable)
THEN 'Latest data'
ELSE 'Old data'
END
SET #i = #i + 1
END
DROP TABLE #ControlTable
You don't need a loop or joins at all. You can simply calculate a row-number inside a CTE, then update the CTE.
WITH cte AS (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY PID, CID ORDER BY CreatedOn DESC)
FROM masterTable
)
UPDATE cte
SET State = CASE WHEN rn = 1
THEN 'Latest data'
ELSE 'Old data'
END;

Display the sum of sales volume for first half and second half and total sales volume in SQL Server

I am working on an Multi level marketing project and here is my table structure
CREATE TABLE [Changu143Aa].[UserSalesVolume]
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[UserID] [bigint] NULL,
[PSV] [decimal](18, 2) NULL DEFAULT ((0)),
[GSV] [decimal](18, 2) NULL DEFAULT ((0)),
[DateAdded] [datetime] NULL,
[Pin] [uniqueidentifier] NULL
)
I need to display the sales volume as that is sum of sales volume he got from 1-15th of the month if the current date is between 1-15th and 16-30/31st if the date belongs to 16-30/31st i write a query but its not working correctly can any body help me
IF OBJECT_ID('tempdb..#TPersonalSalesVol') IS NOT NULL
DROP TABLE #TPersonalSalesVol
IF OBJECT_ID('tempdb..#MPersonalSalesVol') IS NOT NULL
DROP TABLE #MPersonalSalesVol
CREATE TABLE #TPersonalSalesVol
(
TotalPSV Decimal(18, 2),
TotalGSV Decimal(18, 2),
PSV Decimal(18, 2),
GSV Decimal(18, 2),
MUserID bigint
)
CREATE TABLE #MPersonalSalesVol
(
PSV Decimal(18, 2),
GSV Decimal(18, 2),
MUserID bigINT
)
INSERT INTO #MPersonalSalesVol (PSV, GSV, MUserID)
SELECT
SUM(at.PersonalSalesVolume) as PSV,
SUM(at.GroupSalesVolume) as GSV,at.UserID
FROM
UserSalesVolume AS at
WHERE
DATEPART(month,DateAdded) = DATEPART(month,GetDate())
AND DATEPART(day,DateAdded)/16 = DATEPART(day,GetDate())/16
GROUP BY
at.UserID, CONVERT(DATE, at.DateAdded, 101)
INSERT INTO #TPersonalSalesVol (TotalPSV, TotalGSV, PSV, GSV, MUserID)
SELECT
SUM(at.PersonalSalesVolume) as TotalPSV,
SUM(at.GroupSalesVolume) as TotalGSV,
t.PSV, t.GSV, at.UserID
FROM
#MPersonalSalesVol AS t
JOIN
UserSalesVolume AS at ON at.UserID = t.MUserID
GROUP BY
at.UserID, t.PSV, t.GSV
SELECT *
FROM #TPersonalSalesVol
DECLARE #CurDate datetime2(7) = '2016-10-16'
DECLARE #Year int = YEAR(#CurDate)
DECLARE #Month int = MONTH(#CurDate)
-- Calc Day Range
DECLARE #StartDay int = CASE WHEN DAY(#CurDate) <= 15 THEN 1 ELSE 16 END
DECLARE #EndDay int = CASE WHEN DAY(#CurDate) <= 15 THEN 15 ELSE 31 END
SELECT UserID, SUM(PSV), SUM(GSV)
FROM UserSalesVolume
WHERE YEAR(DateAdded) = #Year AND MONTH(DateAdded) = #Month
AND DAY(DateAdded) BETWEEN #StartDay AND #EndDay
GROUP BY UserID

Multiple Table Insert with Merge?

I am trying to insert some rows in a parent/child relationship. How does one accomplish this in SQL?
This would be the base query I'd use to find the info I would be inserting:
SELECT * FROM parentTable p
INNER JOIN childTable c
ON p.ID = c.ParentTableID
WHERE p.PlanID = 123456
What needs to happen is that I insert the ParentTable row first which is really just a copy of the matched row but with a new PlanID and Created Date. Then I take that ParentTable ID from the inserted row and use that for the same process but for the Child Table.
So I need to do in .Net speak at least is where I loop through all parentTable matches and for each match create 1 childTable row.
I was trying to use MERGE and the OUTPUT clause but it seems like I'm maybe using a square peg for a round hole. Would I be better off using a CURSOR of some sorts?
So this is what I have so far based on the answer below. Unfortunately it isn't grabbing the SCOPE_IDENTITY()...is there a trick to it? Because that is returning NULL I get FK errors on the inserts.
USE MemberCenteredPlan
DECLARE #NewPlanID BIGINT;--49727690
DECLARE #OldPlanID BIGINT;--49725211
DECLARE #NewSWReAssID BIGINT;
SET #NewPlanID = 49727690
SET #OldPlanID = 49725211
BEGIN
INSERT INTO tblSocialWorkerReAssessment
SELECT
#NewPlanID
,[Discussed]
,Discussion
,NULL
,NULL
,NULL
,CreatedBy
,GETDATE()
,NULL
,NULL
FROM tblSocialWorkerReAssessment
WHERE PlanID = #OldPlanID
SELECT #NewSWReAssID = SCOPE_IDENTITY();
INSERT INTO tblPlanDomain
SELECT
#NewPlanID
,[DomainTypeID]
,[MemberOutcomes]
,[MemberPreferences]
,[DomainDate]
,[Steps]
,[ClinicalFunctionalConcerns]
,[ReportWageES]
,[ReportWageSSA]
,#NewSWReAssID
,[CreatedBy]
,GETDATE()
,NULL
,NULL
,NEWID()
FROM tblPlanDomain
WHERE planID = #OldPlanID
END
You don't need MERGE and you definitely don't need cursors. And an INSERT (or a MERGE) can only ever affect one table at a time, so you'll need to perform multiple statements anyway. If you are only ever dealing with one plan at a time, you can do this:
DECLARE #NewPlanID INT;
INSERT dbo.ParentTable(cols...)
SELECT cols...
FROM dbo.ParentTable WHERE PlanID = 123456;
SELECT #NewPlanID = SCOPE_IDENTITY();
INSERT dbo.ChildTable(ParentTableID, cols...)
SELECT #NewPlanID, cols...
FROM dbo.ChildTable WHERE PlanID = 123456;
If you need to reference multiple new plans, it gets a little more complicated, and in that case you would need to use MERGE (at the present time, INSERT's composable DML is a little on the light side - you can't reference the source table in the OUTPUT clause).
DECLARE #p TABLE(OldPlanID INT, NewPlanID INT);
MERGE dbo.ParentTable WITH (HOLDLOCK)
USING
(
SELECT ID, cols... FROM dbo.ParentTable
WHERE ID IN (123456, 234567)
) AS src ON src.ID IS NULL
WHEN NOT MATCHED THEN INSERT(cols...)
VALUES(src.cols...)
OUTPUT src.ID, inserted.ID INTO #p;
INSERT dbo.ChildTable(ParentTableID, cols...)
SELECT p.NewPlanID, t.cols...
FROM dbo.ChildTable AS t
INNER JOIN #p AS p
ON t.ParentTableID = p.OldPlanID;
However, you should be very wary about this... I link to several issues and unresolved bugs with MERGE in this answer over on dba.SE. I've also posted a cautionary tip here and several others agree.
I think this is what you're after.
Use Northwind
GO
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#OrderAuditHolder') IS NOT NULL
begin
drop table #OrderAuditHolder
end
CREATE TABLE #OrderAuditHolder
(
[OriginalOrderID] [int] NOT NULL,
[NewOrderID] [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,
)
declare #ExampleOrderID int
select #ExampleOrderID = (select top 1 OrderID from dbo.Orders ords where exists (select null from dbo.[Order Details] innerOD where innerOD.OrderID = ords.OrderID ) )
print '/#ExampleOrderID/'
print #ExampleOrderID
print ''
insert into dbo.Orders (CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry)
output #ExampleOrderID , inserted.OrderID,inserted.CustomerID,inserted.EmployeeID,inserted.OrderDate,inserted.RequiredDate,inserted.ShippedDate,inserted.ShipVia,inserted.Freight,inserted.ShipName,inserted.ShipAddress,inserted.ShipCity,inserted.ShipRegion,inserted.ShipPostalCode,inserted.ShipCountry
into #OrderAuditHolder
Select
CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry
from dbo.Orders where OrderID = #ExampleOrderID
print '/#OrderAuditHolder/'
Select * from #OrderAuditHolder
print ''
Insert into dbo.[Order Details] ( OrderID , ProductID , UnitPrice , Quantity , Discount )
Select
holder.NewOrderID , od.ProductID , od.UnitPrice , od.Quantity , od.Discount
from #OrderAuditHolder holder
join dbo.[Order Details] od on holder.OriginalOrderID = od.OrderID
/* Note, the "join" is on the OriginalOrderID, but the inserted value is the NewOrderID */
/* below is not needed, but shows results */
declare #MaxOrderID int
select #MaxOrderID = (select MAX(OrderID) from dbo.Orders ords where exists (select null from dbo.[Order Details] innerOD where innerOD.OrderID = ords.OrderID ) )
select * from dbo.[Order Details] where OrderID = #MaxOrderID order by OrderID desc
/**/
IF OBJECT_ID('tempdb..#OrderAuditHolder') IS NOT NULL
begin
drop table #OrderAuditHolder
end
SET NOCOUNT OFF

T-SQL join to get both mated and non mated start and stop records

I have a poorly designed table that I did not design and cannot fix/change because a 3rd party blackberry app that writes to it. The meat is that there is a start record and a stop record for tracking events with NO connection or validation that there is a match. The blackberry app does nothing to tie these records together. I have tried to create a join on its self and create temp tables with the begin and one with the end to full outer join them. The problem is that I have duplicate entries were the entry should be marked as having no mate. Existing data has rows with no mate on both the start and end records. I have searched SO for answers and I found some close answers that have led me this far. I know its a long post, sorry for that.
There is a single table that surprisingly has a primary key. There is no pivot/intersection table. Structure is
ID (int PK)
activityType varchar
beginEnd varchar ('begin' or 'end')
businessKey varchar nullable
date DATETIME
technician varchar
The following columns are in the table as well, but are nullable, and not important to the query.
dateSubmitted DATETIME
gpsLatitude float
gpsLongitude float
note varchar
odometer int
The query that I have now that still leaves dupes: Showing and sorting ID and EndID are for debugging only
DECLARE #DateFrom DATETIME
DECLARE #DateTo DATETIME
SET #DateFrom='20101101'
SET #DateTo='20101102'
DECLARE #Incomplete VARCHAR(15)
SET #Incomplete = 'Incomplete'
DECLARE #StartEvents TABLE
(
[id] [numeric](19, 0) NOT NULL,
[activityType] [varchar](255) NOT NULL,
[beginEnd] [varchar](255) NULL,
[businessKey] [varchar](255) NULL,
[date] [datetime] NOT NULL,
[dateSubmitted] [datetime] NULL,
[gpsLatitude] [float] NULL,
[gpsLongitude] [float] NULL,
[note] [varchar](255) NULL,
[odometer] [int] NULL,
[technician] [varchar](255) NOT NULL
)
INSERT #StartEvents
([ID],[activityType],[beginEnd],[businessKey],[date],[dateSubmitted],[gpsLatitude]
,[gpsLongitude],[note],[odometer],[technician])
SELECT *
FROM dbo.TimeEntry
WHERE
[date] between #DateFrom AND #DateTo
AND beginEnd = 'Begin'
--AND [technician] = 'FRED'
ORDER by technician
------------------------------------------------------------
DECLARE #EndEvents TABLE
(
[id] [numeric](19, 0) NOT NULL,
[activityType] [varchar](255) NOT NULL,
[beginEnd] [varchar](255) NULL,
[businessKey] [varchar](255) NULL,
[date] [datetime] NOT NULL,
[dateSubmitted] [datetime] NULL,
[gpsLatitude] [float] NULL,
[gpsLongitude] [float] NULL,
[note] [varchar](255) NULL,
[odometer] [int] NULL,
[technician] [varchar](255) NOT NULL
)
INSERT #EndEvents
([ID],[activityType],[beginEnd],[businessKey],[date],[dateSubmitted],[gpsLatitude]
,[gpsLongitude],[note],[odometer],[technician])
SELECT *
FROM dbo.TimeEntry
WHERE
[date] between #DateFrom AND #DateTo AND
beginEnd = 'End'
--AND [technician] = 'FRED'
ORDER by technician
-- And then a conventional SELECT
SELECT
StartEvents.id
,EndEvents.id AS EndID
,COALESCE(
StartEvents.activityType ,EndEvents.activityType ,'Not Available'
) AS ActivityType
--,StartEvents.beginEnd as [Begin]
--,EndEvents.beginEnd AS [End]
,COALESCE (
convert(VARCHAR(12), StartEvents.[date], 103),
convert(VARCHAR(12), EndEvents.[date], 103), #Incomplete
) as [Event Date]
,COALESCE (
convert(VARCHAR(12), EndEvents.[date], 103), #Incomplete
) as [End Date]
,COALESCE(
CONVERT(VARCHAR(5) , StartEvents.dateSubmitted , 108) , #Incomplete
) AS StartTime
,COALESCE(
CONVERT(VARCHAR(5) , EndEvents.dateSubmitted , 108) , #Incomplete
) AS EndTime
,COALESCE(
StartEvents.note, EndEvents.note, ''
) as [Note]
,COALESCE(
StartEvents.technician,EndEvents.technician,'Not Available'
) AS Technician
FROM
#StartEvents As StartEvents
FULL OUTER JOIN
#EndEvents AS EndEvents ON
StartEvents.technician = EndEvents.technician AND
StartEvents.businessKey = EndEvents.businessKey AND
StartEvents.activityType = EndEvents.activityType
AND convert(VARCHAR(12), StartEvents.[date], 103) = convert(VARCHAR(12), EndEvents.[date], 103)
-- WHERE
--StartEvents.[date] between #DateFrom AND #DateTo OR
--StartEvents.[dateSubmitted] between #DateFrom AND #DateTo
ORDER BY
StartEvents.Technician,
ID,ENDID
DATA:
id,activityType,beginEnd,businessKey,date,dateSubmitted,gpsLatitude,gpsLongitude,note,odometer,technician
23569,Standby,Begin,,2010-11-01 08:00:13.000,2010-11-01 08:26:45.533,34.139,-77.895,#1140,28766,barthur#fubar.com
23570,Travel,Begin,00100228002,2010-11-01 07:00:44.000,2010-11-01 08:34:15.370,35.0634,-80.7668,,18706,creneau#fubar.com
23571,Standby,End,,2010-11-01 08:30:08.000,2010-11-01 08:35:20.463,34.0918,-77.9002,#1140,28766,barthur#fubar.com
23572,Travel,Begin,00100226488,2010-11-01 08:30:41.000,2010-11-01 08:36:56.420,34.0918,-77.9002,,28766,barthur#fubar.com
23573,Travel,End,00100226488,2010-11-01 08:45:00.000,2010-11-01 08:44:15.553,34.0918,-77.9002,,28768,barthur#fubar.com
23574,OnSite,Begin,00100226488,2010-11-01 08:45:41.000,2010-11-01 09:24:23.943,34.0918,-77.9002,,0,barthur#fubar.com
23575,OnSite,End,00100226488,2010-11-01 09:30:10.000,2010-11-01 09:33:19.953,34.0918,-77.9002,,28768,barthur#fubar.com
23576,Travel,Begin,00100228137,2010-11-01 09:30:20.000,2010-11-01 09:34:57.330,34.0918,-77.9002,,28768,barthur#fubar.com
23577,Travel,End,00100228137,2010-11-01 09:45:51.000,2010-11-01 09:42:39.230,34.0918,-77.9002,,28771,barthur#fubar.com
23578,Travel,Begin,00100228138,2010-11-01 09:00:23.000,2010-11-01 09:58:22.857,34.9827,-80.5365,,18749,creneau#fubar.com
23579,OnSite,Begin,00100228137,2010-11-01 09:45:47.000,2010-11-01 10:41:10.563,34.139,-77.895,,0,barthur#fubar.com
23580,OnSite,End,00100228137,2010-11-01 10:45:43.000,2010-11-01 11:09:14.393,34.139,-77.895,,28771,barthur#fubar.com
23581,OnSite,Begin,00100228142,2010-11-01 10:45:42.000,2010-11-01 11:29:26.447,34.139,-77.895,#1015,28771,barthur#fubar.com
23582,OnSite,End,00100228142,2010-11-01 11:15:18.000,2010-11-01 11:55:28.603,34.139,-77.895,#1015,28771,barthur#fubar.com
23583,Travel,Begin,,2010-11-01 11:15:06.000,2010-11-01 11:56:01.633,34.139,-77.895,"#1142 Fuel, #1154 Tickets",28771,barthur#fubar.com
23584,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:07:54.867,34.139,-77.895,"#1154, #1142",28774,barthur#fubar.com
23585,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:07:55.087,34.139,-77.895,"#1154, #1142",28774,barthur#fubar.com
23586,Break,Begin,,2010-11-01 12:00:26.000,2010-11-01 12:08:06.007,34.139,-77.895,#1153,28774,barthur#fubar.com
23587,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:08:06.040,34.139,-77.895,"#1154, #1142",28774,barthur#fubar.com
23588,Break,Begin,,2010-11-01 12:00:26.000,2010-11-01 12:08:06.070,34.139,-77.895,#1153,28774,barthur#fubar.com
23589,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:16:02.673,34.139,-77.895,"#1154, #1142",28774,barthur#fubar.com
23590,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:16:14.220,34.139,-77.895,"#1154, #1142",28774,barthur#fubar.com
23591,Travel,Begin,00100228000,2010-11-01 11:45:19.000,2010-11-01 12:35:46.363,35.0634,-80.7668,,18760,creneau#fubar.com
23592,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:58:51.050,34.0918,-77.9002,,28774,barthur#fubar.com
23593,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.830,34.0918,-77.9002,,28774,barthur#fubar.com
23594,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.893,34.1594,-77.8929,,28774,barthur#fubar.com
23595,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.940,34.1594,-77.8929,,28774,barthur#fubar.com
23596,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.880,34.1594,-77.8929,,28774,barthur#fubar.com
23597,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.927,34.2743,-77.8668,,28774,barthur#fubar.com
23598,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.987,34.2743,-77.8668,,28774,barthur#fubar.com
23599,Travel,Begin,00100228166,2010-11-01 14:00:13.000,2010-11-01 14:29:45.320,35.0634,-80.7668,,18779,creneau#fubar.com
23600,Travel,End,00100227980,2010-11-01 15:15:58.000,2010-11-01 15:15:40.403,35.3414,-78.0325,,28880,barthur#fubar.com
23601,Travel,Begin,00100228205,2010-11-01 15:30:46.000,2010-11-01 15:41:41.810,35.0661,-80.8376,,18781,creneau#fubar.com
23602,OnSite,Begin,00100227980,2010-11-01 15:15:23.000,2010-11-01 15:59:45.203,35.3873,-77.9395,,28880,barthur#fubar.com
23603,OnSite,End,00100227980,2010-11-01 16:15:22.000,2010-11-01 16:06:09.150,35.3873,-77.9395,,28880,barthur#fubar.com
23604,Travel,Begin,00100228007,2010-11-01 16:15:15.000,2010-11-01 16:15:25.253,35.3873,-77.9395,,28880,barthur#fubar.com
23605,Travel,Begin,,2010-11-01 16:15:12.000,2010-11-01 16:20:49.933,35.0445,-80.8227,Return trip home,18785,creneau#fubar.com
23606,Travel,End,00100228007,2010-11-01 16:30:48.000,2010-11-01 16:26:43.360,35.3873,-77.9395,,28884,barthur#fubar.com
23607,Travel,End,,2010-11-01 17:30:14.000,2010-11-01 17:23:57.897,35.2724,-81.1577,Return trip home,18822,creneau#fubar.com
23608,OnSite,Begin,00100228007,2010-11-01 16:30:48.000,2010-11-01 18:38:32.700,35.3941,-77.994,,28880,barthur#fubar.com
23609,Travel,Begin,00100228209,2010-11-01 17:45:16.000,2010-11-01 18:39:05.683,35.3941,-77.994,,28884,barthur#fubar.com
23610,OnSite,End,00100228007,2010-11-01 17:45:52.000,2010-11-01 18:41:36.980,35.3941,-77.994,,28884,barthur#fubar.com
23611,OnSite,Begin,00100228209,2010-11-01 18:00:38.000,2010-11-01 18:42:12.763,35.3941,-77.994,,28888,barthur#fubar.com
23612,OnSite,End,00100228209,2010-11-01 18:30:44.000,2010-11-01 18:43:29.123,35.3941,-77.994,,28888,barthur#fubar.com
23613,Standby,Begin,,2010-11-01 18:30:58.000,2010-11-01 18:45:28.857,35.3941,-77.994,#1157 ergo,28888,barthur#fubar.com
23614,Standby,End,,2010-11-01 18:45:26.000,2010-11-01 18:46:01.167,35.3941,-77.994,#1157 ergo redo,28888,barthur#fubar.com
23615,Travel,Begin,,2010-11-01 18:45:24.000,2010-11-01 18:47:37.803,35.3941,-77.994,RTN,28888,barthur#fubar.com
23616,Travel,End,,2010-11-01 20:45:05.000,2010-11-01 20:34:39.433,34.139,-77.895,#1142 Fueled,28990,barthur#fubar.com
In this image you see that the highlighted rows are showing 6 end times with the same begin times. and records 14 and 15 show 2 begins and no ends.
Here is a method which abuses the row_number function. Please check the comments for some explanation.
;with Seq as (
-- Create a master sequence of events
-- Trust the date column to be accurate (don't match a Begin to an earlier End)
select id, activitytype, beginend
, coalesce(businesskey, '') as businesskey -- Needed to match nulls as equal
, [date], technician, note
, row_number() over (partition by technician, businesskey, activitytype order by [date], beginend, id) as rownumber
from TimeEntry
)
select b.id as BeginID
, e.id as EndID
, coalesce(b.technician, e.technician) as Technician
, coalesce(b.businesskey, e.businesskey) as BusinessKey
, coalesce(b.activitytype, e.activitytype) as ActivityType
, coalesce(convert(char(10), b.[date], 103), 'Incomplete') as BeginDate
, coalesce(convert(char(10), e.[date], 103), 'Incomplete') as EndDate
, coalesce(convert(char(5), b.[date], 108), 'Incomplete') as BeginTime
, coalesce(convert(char(5), e.[date], 108), 'Incomplete') as EndTime
, b.note as BeginNote
, e.note as EndNote
from (select * from Seq where beginend = 'Begin') b -- Get all Begins
full outer join (select * from Seq where beginend = 'End') e -- Get all Ends
on b.technician = e.technician
and b.businesskey = e.businesskey
and b.activitytype = e.activitytype
and b.rownumber = e.rownumber - 1 -- Match a Begin with only the very next End of that type
order by coalesce(b.[date], e.[date])
, coalesce(b.id, e.id)
, coalesce(b.technician, e.technician)
, coalesce(b.businesskey, e.businesskey)
, coalesce(b.activitytype, e.activitytype)
And the SQL Fiddle should anyone want the DDL or demo.
Using CTE's and Row_Number() I think I can return what you are looking for. The key is to only perform your full outer by joining on adajacent rows based upon an ordering of technician, businesskey, activitytype. Anyway here it is:
WITH EventsCTE
AS
(
select id, technician,businessKey,activityType,
CAST(date as date) As date, dateSubmitted,
beginEnd, note,
ROW_NUMBER() OVER
(Partition BY technician,
businesskey, activityType
ORDER BY dateSubmitted) as rowN
from TimeEntry
),
BeginEventsCTE
AS
(
select id, technician,businessKey,activityType,
CAST(date as date) As date,
dateSubmitted, note, rowN
from EventsCTE
WHERE beginEnd = 'Begin'
),
EndEventsCTE
AS
(
select id, technician,businessKey,
activityType, CAST(date as date) As date,
dateSubmitted, note, rowN
from EventsCTE
WHERE beginEnd = 'End'
)
SELECT B.id,
E.id As EndId,
COALESCE(B.activityType ,E.activityType ,'Not Available') AS ActivityType,
COALESCE(convert(VARCHAR(12), B.[date], 103), 'Incomplete') As EventDate,
COALESCE(convert(VARCHAR(12), E.[date], 103), 'Incomplete') As EndDate,
COALESCE(CONVERT(VARCHAR(5) , B.dateSubmitted , 108) , 'Incomplete') As StartTime,
COALESCE(CONVERT(VARCHAR(5) , E.dateSubmitted , 108) , 'Incomplete') As EndTime,
COALESCE(B.Note, E.note, '') as Note,
COALESCE(B.technician, E.technician, 'Not Available') As Technician --, B.rowN, E.rowN
FROM BeginEventsCTE B
FULL OUTER join EndEventsCTE E
ON B.technician = E.technician AND
B.businessKey = E.businessKey AND
B.activityType = E.activityType AND
B.date = E.date AND
B.rowN = E.rowN - 1
ORDER BY
COALESCE(B.Technician, E.Technician),
COALESCE(b.id,E.id)
And here's the results:

Correlated join with outer fields as parameters

I need a way to join a table with a function's results. I'm not sure if it's possible and somehow I don't think it's a good idea. Let me try and explain the situation.
There is a table [Entities]:
[ID] [Description] [kWh] [kVArh] [kVAh] [OfferID] [CustomOfferID]
Another table [Data]:
[ID] [Timestamp] [Value]
And a function:
[Calc] (#offer, #customOffer, #kWh, #kVArh, #kVAh, #dtStart, #dtEnd)
So you can see there are entities, the entities' data (usage) and a function to calculate the cost.
I need to display the usage and cost of multiple entites:
[Description] [MWh] [MVA] [Cost]
[MWh] will be a SUM of all the entity's data over the period; [MVA] will be the MAX of all the data over the period; and [Cost] will SUM the [Cost] field from the sub query (function).
The query I figured would do the jobs looks like this:
SELECT [tc].[ID], [tc].[Desc]
, SUM([kWh].[Value]) / 1000 AS [MWh]
, MAX([kVAh].[Value]) / 1000 AS [MVA]
, SUM([cost].[Cost])
FROM [Tree_Cost] AS [tc]
INNER JOIN [Data] AS [kWh] ON [tc].[kWh] = [kWh].[ID]
INNER JOIN [Data] AS [kVAh] ON [tc].[kVAh] = [kVAh].[ID]
INNER JOIN
(
SELECT [tc].[ID], [Cost]
FROM [Calc] ([tc].[Offer_ID], [tc].[OfferCustom_ID], [tc].[kWh], [tc].[KVArh], [tc].[kVAh], #dtStart, #dtEnd)
) AS [cost] ON [tc].[ID] = [cost].[ID]
WHERE [tc].[Type] = 1 AND [tc].[TypeDesc] = 'GF_K_M'
AND [kWh].[Timestamp] BETWEEN #dtStart AND #dtEnd
AND [kVAh].[Timestamp] BETWEEN #dtStart AND #dtEnd
GROUP BY [tc].[ID], [tc].[Desc]
The real problem here is that I need to include the [ID] from the outer query in the result set of the inner query (function) in order to be able to join the two. Then I also need to be able to use the fields from the outer query as arguments for the inner query (function).
This is obviously not the way seeing as the [tc] identifier is not recognized in the inner query. So how am I supposed to accomplish something like this?
CREATE FUNCTION [dbo].[Calc]
( \#intOffer [int]
, \#intCustom [int]
, \#intP [int]
, \#intQ [int]
, \#intS [int]
, \#dtStart [datetime]
, \#dtEnd [datetime]
)
RETURNS TABLE
( [Entry] [nvarchar](200) NULL
, [Rate] [float] NULL
, [Unit] [nvarchar](50) NULL
, [Reading] [float] NULL
, [Cost] [float] NULL
, [DDate] [nvarchar](50) NULL
)
WITH EXECUTE AS CALLER
AS EXTERNAL NAME [OfferCalcLite].[UserDefinedFunctions].[SqlArray]
I'm not sure I understand correctly. Perhaps you can completely drop the JOIN:
INNER JOIN
(
SELECT [tc].[ID], [Cost]
FROM [Calc] ([tc].[Offer_ID], [tc].[OfferCustom_ID], [tc].[kWh], [tc].[KVArh], [tc].[kVAh], #dtStart, #dtEnd)
) AS [cost] ON [tc].[ID] = [cost].[ID]
and change:
, SUM([cost].[Cost])
into:
, SUM( [Calc] ( [tc].[Offer_ID]
, [tc].[OfferCustom_ID]
, [tc].[kWh]
, [tc].[KVArh]
, [tc].[kVAh]
, #dtStart, #dtEnd
)
) AS Cost