SQL - How to use the output from an insert to update a table - sql

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.

Related

SQL - Joining to Nonexistent Records

After doing a bit of looking, I thought maybe I'd found a solution here: sql join including null and non existing records. Cross Joining my tables seems like a great way to solve my problem, but now I've hit a snag:
Below are the tables I’m using:
CREATE TABLE [dbo].[DCRSales](
[WorkingDate] [smalldatetime] NOT NULL,
[Store] [int] NOT NULL,
[Department] [int] NOT NULL,
[NetSales] [money] NOT NULL,
[DSID] [int] IDENTITY(1,1) NOT NULL)
CREATE TABLE [dbo].[Stores](
[Number] [int] NOT NULL,
[Has_Deli] [bit] NOT NULL,
[Alcohol_Register] [int] NULL,
[Is_Cost_Saver] [bit] NOT NULL,
[Store_Status] [nchar](10) NOT NULL,
[Supervisor_Number] [int] NOT NULL,
[Email_Address] [nchar](20) NOT NULL,
[Sales_Area] [int] NULL,
[PZ_Store_Number] [int] NULL,
[Has_SCO] [bit] NULL,
[SCO_Reg] [nchar](25) NULL,
[Has_Ace] [bit] NULL,
[Ace_Sq_Ft] [int] NULL,
[Open_Date] [datetime] NULL,
[Specialist] [nchar](2) NULL,
[StateID] [int] NOT NULL)
CREATE TABLE [dbo].[DepartmentMap](
[Department_Number] [int] NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[Parent_Department] [int] NOT NULL)
CREATE TABLE [dbo].[ParentDepartments](
[Parent_Department] [int] NOT NULL,
[Description] [varchar](50) NULL
DCRSales is a table holding new and archived data. The archived data is not perfect, meaning that there are of course certain missing date gaps and some stores which currently have a department they didn't have or no longer have a department they used to have. My goal is to join this table to our department list, list the child departments and parent departments and SUM up the netsales for a given date range. In cases where a store does not have a department whatsoever in that date range, I still need to display it as 0.00.
A more robust solution would probably be to just store all departments for each store regardless of whether they have that department or not (with sales set to 0.00 of course). However I imagine doing that and/or solving my problem here would require very similar queries anyway.
The query I have tried is as follows:
WITH CTE AS (
SELECT S.Number as Store, DepartmentMap.Department_Number as Department, ParentDepartments.Parent_Department as Parent, ParentDepartments.Description as ParentDescription, DepartmentMap.Description as ChildDescription
FROM Stores as S CROSS JOIN dbo.DepartmentMap INNER JOIN ParentDepartments ON DepartmentMap.Parent_Department = ParentDepartments.Parent_Department
WHERE S.Number IN(<STORES>) AND Department_Number IN(<DEPTS>)
)
SELECT CTE.Store, CTE.Department, SUM(ISNULL(DCRSales.NetSales, 0.00)) as Sales, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription
FROM CTE LEFT JOIN DCRSales ON DCRSales.Department = CTE.Department AND DCRSales.Store = CTE.Store
WHERE DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>' OR DCRSales.WorkingDate IS NULL
GROUP BY CTE.Store, CTE.Department, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription
ORDER BY CTE.Store ASC, CTE.Department ASC
In this query I try to CROSS JOIN each department to a store from the Stores table so that I can get a combination of every store and every department. I also include the Parent Departments of each department along with the child department's description and the parent department's description. I filter this first portion based on store and department, but this does not change the general concept.
With this result set, I then try to join this table to all of the sales in DCRSales that are within a certain date range. I also include the date if it’s null because the results that have a NULL sales also have a NULL WorkingDate.
This query seemed to work, until I noticed that not all departments are being used with all stores. The stores in particular that do not get combined with all departments are the ones that have no data for the given date range (meaning they have been closed). If there is no data for the department, it should still be listed with its department number, parent number, department description and parent description (with Sales as 0.00). Any help is greatly appreciated.
Your WHERE clause is filtering out records that do have sales at some point in time, but not for the desired period of time, those records don't meet either criteria and are therefore excluded.
I might be under-thinking it, but might just need to move:
DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>'
To your LEFT JOIN criteria and get rid of WHERE clause. If that's not right, you could filter sales by date in a 2nd cte prior to the join.
What you want is an OUTER JOIN.
See this: https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx
I suggest that this process is probably much too complicated to be done using a single query. I think that you need to perform several queries: to extract the transactions-of-interest into a separate table, then to modify the results one-or-more times in that table before using it to produce your final statistics. A stored procedure, which drives several separately stored queries, could be used to drive the process, which, in several "stages," makes several "passes" over the initially-extracted data.
One piece of important information, for instance, would be to know when a particular store had a particular department. (For instance: store, department, starting_date, ending_date.) This would be a refinement of a possibly-existing table (and, maybe, drawn from it ...) which lists what departments a particular store has today.
Let us hope that department-numbers do not change, or that your company hasn't acquired other companies with the resulting need to "re-map" these numbers in some way.
Also: frankly, if you have access to a really-good statistics package, such as SAS® or SPSS® ... can "R" do this sort of thing? ... you might find yourself better-off. (And no, I don't mean "Microsoft Excel ...") ;-)
When I have been faced with requirements like these (and I have been, many times ...), a stats-package was indispensable. I found that I had to "massage" the process and the extracted data a number of times, in a system of successive-refinement that gradually lead me to a reporting process that I could trust and therefore defend.

insert rows to column wise in sql server [duplicate]

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]

Why database does not recognize the columns and table?

I have created a table in there is data in the table,
I can insert, update ect.
CREATE TABLE [dbo].[cse_reports_month](
[report_id] [int] IDENTITY(1,1) NOT NULL,
[starburst_dept_name] [varchar](50) NULL,
....more collumns
[shooting_total_stars] [float] NULL,
) ON [PRIMARY]
but for some reason when I hover over the columns name, for example
select the top 1000 rows :
SELECT TOP 1000 [report_id]
,[starburst_dept_name]
,[starburst_dept_average]
...... more columns
,[rising_star_dept_name]
FROM [Intranet].[dbo].[cse_reports_month]
It says "invalid column name 'starburst_dept_name'"
It like it does not requinize it, but all my other tables are
good.
Wondering why it does not recognize the columns?
I have
Microsoft SQL Server Management Studio 10.0.2531.0

SQL query align sequence of events in one row

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

How to update 2nd table with identity value of inserted rows into 1st table

I have the following table structures
CREATE TABLE [dbo].[WorkItem](
[WorkItemId] [int] IDENTITY(1,1) NOT NULL,
[WorkItemTypeId] [int] NOT NULL,
[ActionDate] [datetime] NOT NULL,
[WorkItemStatusId] [int] NOT NULL,
[ClosedDate] [datetime] NULL,
)
CREATE TABLE [dbo].[RequirementWorkItem](
[WorkItemId] [int] NOT NULL,
[RequirementId] [int] NOT NULL,
)
CREATE TABLE #RequirmentWorkItems
(
RequirementId int,
WorkItemTypeId int,
WorkItemStatusId int,
ActionDate datetime
)
I use the #RequirmentWorkItems table to create workitems for requirements. I then need to INSERT the workitems into the WorkItem table and use the identity values from the WorkItem table to create the cross-reference rows in the RequirementWorkItem table.
Is there a way to do this without cursoring thru each row? And I can't put the RequirementId into the WorkItem table because depending on the WorkItemTypeId the WorkItem could be linked to a Requirement or a Notice or an Event.
So there are really 3 xref tables for WorkItems. Or would it be better to put a RequirementId, NoticeId and EventId in the WorkItem table and 1 of the columns would have a value and other 2 would be null? Hopefully all this makes sense. Thanks.
You should read MERGE and OUTPUT – the swiss army knife of T-SQL for more information about this.
Today I stumbled upon a different use for it, returning values using an OUTPUT clause from a table used as the source of data for an insertion. In other words, if I’m inserting from [tableA] into [tableB] then I may want some values from [tableA] after the fact, particularly if [tableB] has an identity. Observe my first attempt using a straight insertion where I am trying to get a field from #source.[id] that is not used in the insertion: