Hope you all enjoying holidays and fun time. Reply to this when you get a chance.
I'm using SQL Server 2005.
The issues is - there is a process in one of our teams which do things in sequence of events/actions. Mostly it is 4 actions/events for every sequence. These events are fixed. When they perform this DWH gets an entry for each event as a separate row.
Example
1) Call Customer
2) Sell Insurance
3) Send PDS
4) Send details to product team
I've it set in a way that all Actions and their definitions are in Dimension_Point_Code table. All events that come through from DWH are treated as Fact and stored in Fact_Point
The Point here refers to the Point in the sequence of the process.
So the table that store this info looks like below
Dimension table
CREATE TABLE [tbl_Dim_Point_Code]
(
[Point_Code_Key] [int] IDENTITY(101,1) NOT NULL,
[Point_Code] [varchar](8) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Point_Code_TouchPoint] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
Fact Table
CREATE TABLE [tbl_FACT_Point]
(
[Point_Key] [bigint] IDENTITY(100,1) NOT NULL,
[Point_Code_Key] [int] NOT NULL,
[Customer_Number] [varchar](19) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Sale_Date] [datetime] NULL,
[Rep_ID] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
Data in Dimension
INSERT INTO [tbl_Dim_Point_Code]
([Point_Code]
,[Point_Code_TouchPoint])
Select 'CALC' as Point_Code,'Point1' as Point_Code_TouchPoint
UNION
Select 'SELL' as Point_Code,'Point2' as Point_Code_TouchPoint
UNION
Select 'SPDS' as Point_Code,'Point3' as Point_Code_TouchPoint
UNION
Select 'TPRD' as Point_Code,'Point4' as Point_Code_TouchPoint
Data in Fact
INSERT INTO [tbl_FACT_Point]
([Point_Code_Key]
,[Customer_Number]
,[Sale_Date]
,[Rep_ID])
Select 101,'C101501','24-Feb-2012','ABC'
UNION
Select 102,'C101501','24-Feb-2012','ABC'
UNION
Select 103,'C101501','26-Feb-2012','DEF'
UNION
Select 104,'C101501','27-Feb-2012','XYZ'
UNION
Select 101,'C101502','2-Feb-2012','GHI'
UNION
Select 102,'C101502','2-Feb-2012','GHI'
UNION
Select 104,'C101502','4-Feb-2012','XYZ'
UNION
Select 101,'C101503','14-Feb-2012','ABC'
UNION
Select 103,'C101503','20-Feb-2012','ABC'
UNION
Select 104,'C101503','22-Feb-2012','BBC'
UNION
Select 101,'C101501','24-Oct-2012','ABC'
UNION
Select 102,'C101501','24-Oct-2012','ABC'
UNION
Select 103,'C101501','26-Oct-2012','DEF'
UNION
Select 104,'C101501','27-Oct-2012','XYZ'
Points to note
1) As you can see Customer C101501 was called & sold the twice.
2) And the processing for the all involved happends everyday - like the team, the DWH and the SQL Server Process. Hence most of the times we will not know what is going to happen. We will only know that Event 1 has occured. then few days later event 2 and so on.
3) 101 & 104 are mandatory events. 102 and 103 may or may not occur. The team will contact Product team irrespective of sale or not.
Now - what we want is that the entries to be transposed into this table
CREATE TABLE [tbl_Process1_EVENT]
(
[HS_EVENT_KEY] [int] IDENTITY(101,1) NOT NULL,
[Customer_Number] [varchar](19) ,
[Import_Date] [datetime] NULL,
[Point1_Date_Called] [datetime] NULL,
[Point1_PointCode] [varchar](8) ,
[Point1_Rep_Id] [varchar](50) ,
[Point2_Date_Sold] [datetime] NULL,
[Point2_PointCode] [varchar](8) ,
[Point2_Rep_Id] [varchar](50) ,
[Point3_Date_PDSSent] [datetime] NULL,
[Point3_PointCode] [varchar](8) ,
[Point3_Rep_Id] [varchar](50) ,
[Point4_Date_ProdTeamXfer] [datetime] NULL,
[Point4_PointCode] [varchar](8) ,
[Point4_Rep_Id] [varchar](50)
) ON [PRIMARY]
What I'd want to happen is, an output like this.
Customer_Number Import_Date Point1_Date_Called Point1_PointCode Point1_Rep_Id Point2_Date_Sold Point2_PointCode Point2_Rep_Id Point3_Date_PDSSent Point3_PointCode Point3_Rep_Id Point4_Date_ProdTeamXfer Point4_PointCode Point4_Rep_Id
C101501 28/02/2012 24/02/2012 CALC ABC 24/02/2012 SELL ABC 26/02/2012 SPDS DEF 27/02/2012 TPRD XYZ
C101502 3/02/2012 2/02/2012 CALC GHI 2/02/2012 SELL GHI NULL NULL NULL 4/02/2012 TPRD ABC
C101503 23/02/2012 14/02/2012 CALC ABC NULL NULL NULL 20/02/2012 SPDS ABC 22/02/2012 TPRD BBC
C101501 28/10/2012 24/10/2012 CALC ABC 24/10/2012 SELL ABC 26/10/2012 SPDS DEF 27/10/2012 TPRD XYZ
Transposing the data into rows with new entry for C101501 if new sale is made on same customer.
Import_date is the date when the Row is Updated.
As i said processing happens everyday.
So if I can elaborate this table for line 1 of this output
On 24/02/2012 the Event CALC occurs - we know about this on 25/02/2012 Point 1 & Point 2 on 25/02 will be filled with data and Point 3 & Point 4 will be empty. Import_Date - will be 25/02/2012
On 26/02/2012 PDS is sent which is point 3. So the same row will be updated. Point 3 only will be updated. Import_date will be 27/02/2012
On 27/02/2012 Point 4 event occurs. Hence on 28/02/2012 the same row will be updated with Point 4 details.
That's all I can think about the issue.
Please any help any time will be greatly appreciated.
Njoy holidays and have a good time.
PS: I may have done something wrrong with the format of output. Please advise I can make it better.
I think you need to use the pivot command (aka cross tab). Its not easy to get your head around:
the following links should / could help:
http://geekswithblogs.net/lorint/archive/2006/08/04/87166.aspx
http://msdn.microsoft.com/en-us/library/ms177410%28v=sql.105%29.aspx
http://www.mssqltips.com/sqlservertip/1019/crosstab-queries-using-pivot-in-sql-server/
http://www.simple-talk.com/blogs/2007/09/14/pivots-with-dynamic-columns-in-sql-server-2005/
good lucj
Related
I have two tables one big mastertable and one small helper table. I need to fill values from the helper table into the mastertable. A value from the helper table has a timestamp and it shall be assigned to the next bigger timestamp occurring in the mastertable
example:
master
timestamp
mode
ID
job
2022-05-30 09:15:18.907
abc
65
Null
2022-05-29 09:07:12.980
abc
64
Null
2022-05-28 09:02:00.977
abc
63
Null
2022-05-27 09:12:24.677
abc
62
Null
helper
trigger
job
2022-05-30 09:13:12.000
1910
2022-05-29 09:05:05.000
1611
result
timestamp
mode
ID
job
2022-05-30 09:15:18.907
abc
65
1910
2022-05-29 09:07:12.980
abc
64
1611
2022-05-28 09:02:00.977
abc
63
Null
2022-05-27 09:12:24.677
abc
62
Null
The entries are deleted from helper.
It's pretty simple to do it by hand, but I can't come up with any logic that automates this process
Assuming the possibility of a timestamp being the next bigger time to more than one trigger time it is allowed to overwrite an already assigned job value.
Create example code
CREATE TABLE [BigTable](
[timestamp] [datetime] NOT NULL,
[mode] [varchar](20) NOT NULL,
[ID] [smallint] NOT NULL,
[job] [smallint] NULL,
)
Insert Into [BigTable] values
('2022-05-30T09:15:18.907','abc',65,Null),
('2022-05-29T09:07:12.980','abc',64,Null),
('2022-05-28T09:02:00.977','abc',63,Null),
('2022-05-27T09:12:24.677','abc',62,Null)
CREATE TABLE [SmallTable](
[trigger] [datetime] NOT NULL,
[job] [smallint] NOT NULL,
)
Insert Into [SmallTable] values
('2022-05-30T09:05:05.000',1910),
('2022-05-29T09:13:12.000',1611)
details aren't consistent in your question - desired result and test code data...
used samples from the tables.
anyways, you can tweak a bit if necessary
select b.*, c.*
from bigtable as b
outer apply (
select top 1
s.job
from smalltable as s
where b.[timestamp] > s.[trigger]
) c
I have a document table - see below for definition
In this table We have a root document which has a OriginalDocID of null
Every time a revision is made a new entry is added with the parents documentID as the OriginalDocID
What I am looking to do is to be able to group/partition everything around the Original document that has OriginalDocID of null
Each document can have multiple revisions from one point of origin.
meaning we can have
Doc Id 1 -> 2 -> 3
2 -> 8 -> 9
1 -> 4 -> 7
5 -> 10
So what I would hope to see back is all the rows with the root document. appended
I hope this makes sense. For the life of me I can't wrap my head around a sufficient query.
CREATE TABLE [dbo].[Document](
[DocumentID] [int] IDENTITY(1,1) NOT NULL,
[DocumentName] [varchar](max) NOT NULL,
[ContentType] [varchar](50) NULL,
[DocumentText] [varchar](max) NULL,
[DateCreated] [datetime] NULL,
[DocumentTypeId] [int] NULL,
[Note] [varchar](8000) NULL,
[RefID] [int] NULL,
[Version] [int] NULL,
[Active] [bit] NULL,
[OriginalDocID] [int] NULL
)
You'll need to use a Recursive CTE to do this. That's a query that refers back to itself so it can traverse a hierarchy and gather information as it works it's way down (or up) the levels of that hierarchy.
In your case, something like:
WITH RECURSIVE docCTE AS
(
/* Recursive Seed */
SELECT
cast(null as int) as parentdoc
documentID,
0 as depth,
documentid as originalDocument,
CAST(null as varchar(100) as docpath
FROM
dbo.document
Where originalDocID IS NULL
UNION ALL
/* Recursive Term */
SELECT
docCTE.DocumentID as parentdoc,
document.documentID,
depth + 1 as depth,
docCTE.originalDocument,
docCTE.Path + '>' + document.documentID
FROM
docCTE
INNER JOIN dbo.document on doccte.document = document.originalDocID
WHERE
depth <= 15 /*Keep it from cycling in case of bad hierarchy*/
)
SELECT * FROM docCTE;
The recursive CTE is made up of two parts.
The recursive seed, which is what we use to kick of the query. This is all document records where the originalDocID is null.
The recursive term, where we join the table back to the recursive CTE establishing the parent/child relationship.
In your case we capture the documentid in the Recursive Seed as the originalDoc so that we can bring that down through each record found when we start traversing the hierarchy of documents.
These can be a little overwhelming when you get started, but after you write it a few times, it's second nature (and you'll find the really really helpful as you encounter more of this type of data).
This question already has answers here:
Efficiently convert rows to columns in sql server
(5 answers)
Closed 7 years ago.
below is mine table name: sample1
ID NAME ADDRESS
1 DAN NO.10,CHANGJIANG XI STREET,JIANXI DISTRECT ,LUOYANG CITY,HENAN ,CHINA
2 SAM BINALBAGAN NEGROS OCCIDENTAL PHILIPPINES
3 JOSE B-36 L-40 PH-1 ST. JOSEPH VILLAGE 7, MARINIG CABUYAO LAGUNA, 4025
i need to enter the rows to column, but here the challenges is, in sample 2 i have only 4 columns source rows obtained 6 or more while using split function, how can i insert/ append balance data in ADRS4 after inserting datas in columns.
output should be as follows:
ID NAME ADRS1 ADRS2 ADRS3 ADRS4
1 DAN NO.10 NGJIANG XI STREET JIANXI DISTRECT LUOYANG CITY,HENAN ,CHINA
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...);
Where you want to skip a value simply input a null value. So you query should look something like this:
INSERT INTO table_name (name,adrs1,adres2,...)
VALUES (John,Null,Xi Street,...);
Your SQL design is not that great to begin with IMO but that should work with your current setup. I would create a table that has multiple columns then insert as needed, like this:
CREATE TABLE [dbo].[Table_1](
[id] [int] NULL,
[name] [varchar](50) NULL,
[ADRS1] [varchar](50) NULL,
[ADRS2] [varchar](50) NULL,
[ADRS3] [varchar](50) NULL,
[ADRS4] [varchar](50) NULL
) ON [PRIMARY]
QUESTION INFO
Detailed Question
The best way I can explain my question is to explain my desired outcome. I'm trying to take a certain set of offices, insert its data into the dbo.DeliveryLocation table, then take the output inserted.DeliveryLocationId and update the corresponding office's DeliveryLocationId field with that id.
Desired Outcome Example
Office Data Before
OfficeId | DeliveryLocationId
-----------------------------
1 | null
2 | null
3 | null
Run the SQL statement
Office Data After
OfficeId | DeliveryLocationId
-----------------------------
1 | 5
2 | 6
3 | 7
Delivery Location with the DeliveryLocationId of 5 was created with
the data of the Office with OfficeId of 1
Delivery Location with the DeliveryLocationId of 6 was created with
the data of the Office with OfficeId of 2
Delivery Location with the DeliveryLocationId of 7 was created with
the data of the Office with OfficeId of 3
The problem
Per my current SQL script below, you can see that I have the first part (inserting the Office data into the Delivery Location table) complete. The second part (updating the Office with the corresponding DeliveryLocationId of the created Delivery Location) is not complete, and I am unsure how to go about doing that.
My initial thoughts/ solutions
If there would be a way to store the correlated OfficeId and DeliveryLocationId, perhaps we could loop through them and update the offices in a second SQL statement rather than try to create one SQL statement that does everything.
REFERENCES
dbo.DeliveryLocation
[DeliveryLocationId] [int] IDENTITY(1,1) NOT NULL,
[LocationName] [nvarchar](max) NULL,
[ShortName] [nvarchar](max) NULL,
[ValidatedAddressId] [int] NOT NULL,
[DropoffInstruction] [nvarchar](max) NULL,
[PickupInstruction] [nvarchar](max) NULL,
[TaxRate] [decimal](18, 2) NOT NULL,
[Active] [bit] NOT NULL,
[DisableOffices] [bit] NOT NULL
dbo.Office
[OfficeId] [int] IDENTITY(1,1) NOT NULL,
[OfficeName] [nvarchar](max) NULL,
[ValidatedAddressId] [int] NOT NULL,
[ReferralSource] [nvarchar](max) NOT NULL,
[NumberOfEmployees] [int] NOT NULL,
[DeliveryLocationId] [int] NULL
Current SQL
insert into
dbo.DeliveryLocation
(LocationName, ShortName, ValidatedAddressId, Active, DisableOffices)
output
inserted.DeliveryLocationId
select
OfficeName, OfficeName, ValidatedAddressId, 0, 0
from
dbo.Office as o
where
OfficeId in
(
select distinct
OfficeId
from
dbo.[User] as u
where
u.DeliveryLocationId is null
and
u.OfficeId is not null
)
I'm not sure about doing this in an INSERT statement, but if you use a MERGE statement using Office (or a query based on Office) as the source, you'll be able to refer to source.OfficeId as well as inserted.DeliveryLocationId in the OUTPUT clause. You can simply skip the update and delete usage of the MERGE, and only use the ON NOT MATCHED clause.
When I'm doing things like this I put the output into a temp table, then carry out any further updates or inserts I need to do from there.
In case you've not used the MERGE statement before (or even for anyone who just hasn't used all of their capabilities), this is a really fantastic resource on how to use them, and how to use them well: http://www.made2mentor.com/2012/07/got-the-urge-to-merge/
You could do an update join after you insert into delivery location
update dbo.Office
set o.DeliveryLocationID = dl.DeliveryocationID
from Office o
JOIN DeliveryLocation dl on dl.LocationName = o.OfficeName
Assuming that the Office Names are unique. If they are not you may want to add OfficeID to the DeliveryLocations table, at least temporarily, and join on that.
I'm using aspect-oriented programming techniques to create very fine-grained logging for a class library. Each method call will be logged.
I'm trying to develop a stacked bar chart with each call that comes from an instance of a class, with each sub-call occupying space in between the start and finish of the outer call to visually represent the time taken and aid in performance tuning. In order to do this, I need to identify which calls came from the same instance as a given call and lie between its start and end date, provided the CallGUID (primary key for the table). I know I need to double-reference the table, but I've been trying and the result set has the same Ticks for all the calls.
Schema:
USE [Skunkworks]
GO
/****** Object: Table [dbo].[ClassMemberCall] Script Date: 06/09/2009 15:38:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ClassMemberCall](
[CallGUID] [uniqueidentifier] NOT NULL,
[InstanceGUID] [uniqueidentifier] NOT NULL,
[MemberGUID] [uniqueidentifier] NOT NULL,
[StartedOn] [datetime] NOT NULL,
[FinishedOn] [datetime] NULL,
[SerializedResult] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[ExceptionGUID] [uniqueidentifier] NULL,
[SerializedException] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[StartedOnTick] [bigint] NOT NULL,
[FinishedOnTick] [bigint] NULL
Data:
INSERT INTO [ClassMemberCall] ([CallGUID],[InstanceGUID],[MemberGUID],[StartedOn],[FinishedOn],[SerializedResult],
[ExceptionGUID],[SerializedException],
[StartedOnTick],[FinishedOnTick])
VALUES('1F45C171-910B-4F17-9286-3D8CDEB7A0C4','B1AE1340-1ED7-4C69-A964-49429D3F81B8','AF1249C9-7DE7-46BD-8042-9AFBD2DFAC15',
'Jun 9 2009 3:23:00:790PM','Jun 9 2009 3:23:00:837PM',NULL,'A4252B69-99FF-43F9-AA33-E8704478CD3E',
'Logging.Entities.ExceptionResult',633801577807903192,633801577808371951)
INSERT INTO [ClassMemberCall] ([CallGUID],[InstanceGUID],[MemberGUID],[StartedOn],
[FinishedOn],[SerializedResult],[ExceptionGUID],[SerializedException],
[StartedOnTick],[FinishedOnTick])VALUES('82989F3F-56F9-4F0A-9CBF-752FC07BA110','EBDF2013-6858-4DBB-AA8A-D1931FAF0BF8','55FE8E6C-9694-4DD1-9152-DD492102C00C','Jun 9 2009 3:23:00:713PM','Jun 9 2009 3:23:00:713PM',NULL,NULL,NULL,633801577807121927,633801577807121927)
INSERT INTO [ClassMemberCall] ([CallGUID],[InstanceGUID],[MemberGUID],[StartedOn],[FinishedOn],[SerializedResult],[ExceptionGUID],[SerializedException],[StartedOnTick],[FinishedOnTick])VALUES('B9779849-4815-4C92-8F2E-A29CB307B925',
'17D4C08C-1DCD-4CBA-97A4-BE7A2DFF1DAB','8AC8D865-DEB2-4858-ACE5-A9252F484350','Jun 9 2009 3:23:00:790PM','Jun 9 2009 3:23:00:790PM',NULL,NULL,NULL,633801577807903192,633801577807903192)
INSERT INTO [ClassMemberCall] ([CallGUID],[InstanceGUID],[MemberGUID],[StartedOn],[FinishedOn],[SerializedResult],
[ExceptionGUID],[SerializedException],
[StartedOnTick],[FinishedOnTick])VALUES('CAE8210C-617A-49F4-A739-E442F39B55B0',
'D46CFBF8-5DC0-437B-AE58-A9237BF8E1A0','108BC581-A5BA-402C-BA15-B8D1EB0C03F1','Jun 9 2009 3:23:00:650PM','Jun 9 2009 3:23:00:837PM',NULL,NULL,NULL,633801577806496915,633801577808371951)
I'm not sure I get you right, but if I do, something like that seems to do the trick:
select RESULT.* from classmembercall as RESULT
inner join classmembercall as INPUT
ON RESULT.startedontick BETWEEN INPUT.startedontick and INPUT.finishedontick
AND RESULT.finishedontick BETWEEN INPUT.startedontick and INPUT.finishedontick
where INPUT.CallGUID = 'CAE8210C-617A-49F4-A739-E442F39B55B0'
it should give you all calls between start and end tick of given log entry
if you need to filter it additionally by the same InstanceGUID, then:
select RESULT.* from classmembercall as RESULT
inner join classmembercall as INPUT
ON RESULT.startedontick BETWEEN INPUT.startedontick and INPUT.finishedontick
AND RESULT.finishedontick BETWEEN INPUT.startedontick and INPUT.finishedontick
AND RESULT.InstanceGUID = INPUT.InstanceGUID
where INPUT.CallGUID = 'CAE8210C-617A-49F4-A739-E442F39B55B0'
note that given your sample data, you'll always get only the item with provided CallGuild - because all of the rows have different InstanceGUIDs...
Good luck :)