Related
I've seen this question, this and this, however these are not what I want.
Please, do not close my question as it is not duplicate. It is really important to me.
I've managed to pivot a table, but this is not desired result:
The desired result looks like this:
My sample data is(it is just an example as OperatorX and OC columns should be 50 times):
DECLARE #OperatorPrice TABLE (ID INT NOT NULL, OperatorId INT NULL, Price
NUMERIC(18,3) NULL, FName VARCHAR(50) NULL)
INSERT INTO #OperatorPrice (
ID, OperatorId, Price, FName
)
VALUES
(226, 996, 22954,'Operator1')
, (266, 1016, 79011.2, 'Operator3')
, (112, 1029, 14869, 'Operator4')
, (93, 1031, 10568.96, 'Operator5')
DECLARE #TR TABLE
(
ID INT NULL ,
Operator1 DECIMAL(18,3) NULL, OC1 DECIMAL(18,3) NULL, Operator2 DECIMAL(18,3) NULL,
OC2 DECIMAL(18,3) NULL, Operator3 DECIMAL(18,3) NULL, OC3 DECIMAL(18,3) NULL,
Operator4 DECIMAL(18,3) NULL, OC4 DECIMAL(18,3) NULL, Operator5 DECIMAL(18,3) NULL,
OC5 DECIMAL(18,3) NULL
)
Example code:
INSERT #TR
(ID ,
Operator1, OC1, Operator2, OC2, Operator3, OC3, Operator4, OC4,
Operator5, OC5)
SELECT ID ,
Operator1, OC1, Operator2, OC2, Operator3, OC3, Operator4, OC4,
Operator5, OC5
FROM
(SELECT Price, id, FName
FROM #OperatorPrice) AS SourceTable
PIVOT
(
sum(Price)
FOR FName IN (Operator1, OC1, Operator2, OC2, Operator3, OC3,
Operator4, OC4, Operator5, OC5)
) AS PivotTable
SELECT * FROM #TR
How can I insert data into OC columns?
Perhaps something like this.
In your alias SOURCETABLE, we just add a UNION ALL of possible combinations for an ID with NULL values. In this case the MIN(ID) and values 1 - 50
Just be sure to
1) Define #TR with columns Operator1,OC1,..,Operator50,OC50 <<< OC# can be an INT
2) in the FOR Item IN(Operator1,OC1,..,Operator50,OC50)
Example -- Edit Corrected to allow for >9 operators
INSERT #TR
SELECT *
FROM (
Select A.ID
,B.*
From #OperatorPrice A
Cross Apply ( values (FName,Price)
,('OC'+replace(FName,'Operator',''),OperatorID)
) B (Item,Value)
Union All
Select ID=(select min(ID) From #OperatorPrice)
,B.*
From ( Select Top 50 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1 ) A
Cross Apply ( values (concat('Operator',N),NULL)
,(concat('OC',N),NULL)
) B (Item,Value)
) AS SourceTable
PIVOT ( sum(Value) FOR Item IN (Operator1, OC1, Operator2, OC2, Operator3, OC3, Operator4, OC4, Operator5, OC5) ) AS PivotTable
Select * from #TR
Returns -- Notice Operator2
Using your sample tables and data this is pretty easy with conditional aggregation. Not really clear though how you determine which operator number is which. Hopefully you have something better than parsing numbers out of the values but who knows.
select op.ID
, Operator1 = max(case when convert(int, replace(FName, 'Operator', '')) = 1 then Price end)
, OC1 = max(case when convert(int, replace(FName, 'Operator', '')) = 1 then OperatorID end)
, Operator2 = max(case when convert(int, replace(FName, 'Operator', '')) = 2 then Price end)
, OC2 = max(case when convert(int, replace(FName, 'Operator', '')) = 2 then OperatorID end)
, Operator3 = max(case when convert(int, replace(FName, 'Operator', '')) = 3 then Price end)
, OC3 = max(case when convert(int, replace(FName, 'Operator', '')) = 3 then OperatorID end)
, Operator4 = max(case when convert(int, replace(FName, 'Operator', '')) = 4 then Price end)
, OC4 = max(case when convert(int, replace(FName, 'Operator', '')) = 4 then OperatorID end)
, Operator5 = max(case when convert(int, replace(FName, 'Operator', '')) = 5 then Price end)
, OC5 = max(case when convert(int, replace(FName, 'Operator', '')) = 5 then OperatorID end)
from #OperatorPrice op
cross apply
(
values
(1)
,(2)
,(3)
,(4)
)x(N)
group by op.ID
Here is the full stored procedure. When I select everything between "set no count on" and "end" it works perfectly and table zLOC_invValue gets updated with 2 lines.
If I try to right click on the stored procedure node and choose to execute, the return value is 0 and the table is not updated. I also get the message that the query is executed successfully.
USE [TWL_PROD]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Update_invValue]
AS
BEGIN
SET NOCOUNT ON;
select 'S ' + whse as whse, prod, qtyonhand + qtyunavail as qty ,(avgcost+addoncost) as cost into #stock from openquery ( twllive, 'select whse, prod, qtyonhand,qtyunavail,avgcost,addoncost from pub.icsw where cono = ''1'' and whse in (''mtl'', ''nob'', ''tdc'', ''oak'')');
select 'NS ' + whse as whse, prod, sum(quantity) as qty, sum( case when quantity > 0 then amount else -1*amount end) as total_value into #nStock from openquery ( twllive, 'select b.* from pub.icenh a left join pub.icenl b on a.cono = b.cono and a.typecd = b.typecd and a.whse = b.whse and a.prod = b.prod and a.prodcat = b.prodcat and a.seqnoh = b.seqnoh where a.cono = ''1'' and a.typecd = ''n'' and a.whse in (''mtl'', ''tdc'', ''nob'', ''oak'') and a.activefl = 1 ')
group by whse, prod;
select co_num , abs_num as prod, bin_num, total_qty,total_qty * 1.00 as value, item_type into #3pl from openquery (twllive, 'select a.co_num, a.abs_num, a.total_qty, a.bin_num, b.item_type from pub.inventory a left join pub.item b on a.wh_num = b.wh_num and a.abs_num = b.abs_num where a.co_num = ''1'' and a.wh_num = ''mtl'' and bin_num in ( ''dockexpp'', ''dockexca'', ''docktransi'')');
update #3PL set Value = (g.total_value/g.qty) * a.total_qty from #3PL a inner join #nStock g on a.prod = g.prod where A.item_type = 'n' and g.whse = 'NS mtl';
update #3PL set Value = (g.cost) * a.total_qty from #3PL a inner join #Stock g on a.prod = g.prod where A.item_type = 's' and g.whse = 's mtl' ;
select co_num, SUM(case when bin_num = 'dockexpp' and item_type = 's' then value else 0 end) as Stock_Plaspak,SUM(case when bin_num = 'dockexpp' and item_type = 'n' then value else 0 end) as NS_Plaspak , SUM(case when bin_num = 'dockexca' and item_type = 's' then value else 0 end) as Stock_Caratrans , SUM(case when bin_num = 'dockexca' and item_type = 'N' then value else 0 end) as NS_Caratrans, SUM(case when bin_num = 'docktransi' and item_type = 's' then value else 0 end) as Stock_Transit,SUM(case when bin_num = 'docktransi' and item_type = 'n' then value else 0 end) as NS_transit into #3PL1 from #3PL group by co_num;
select * into #temp from (
select 1 as cono, whse, SUM(total_value) as value from #nStock group by whse
union all
select 1 as cono, whse, SUM(qty * cost) as value from #Stock group by whse
union all
select 1 as cono,'S-3PL' as whse, SUM(case when item_type = 's' then value else 0 end) as value from #3pl
union all
select 1 as cono,'NS-3PL' as whse, SUM(case when item_type = 'n' then value else 0 end)as value from #3pl ) "a";
update #temp set value = ((select value from #temp where whse = 'ns mtl') - (select value from #temp where whse = 'ns-3pl') ) where whse = 'ns mtl';
update #temp set value = ((select value from #temp where whse = 's mtl') - (select value from #temp where whse = 's-3pl') ) where whse = 's mtl';
select cono,[NS MTL],[NS NOB],[NS OAK],[NS TDC],[S MTL],[S NOB], [S OAK], [S TDC] into #stock1 from #temp
pivot (max(value) for whse in ([NS MTL],[NS NOB],[NS OAK],[NS TDC],[S MTL],[S NOB], [S OAK], [S TDC])) as PivotTable;
insert into zloc_InvValue select * from (
select 'Stock: ' as [type], GETDATE() as [date], a.[S MTL] as MTL,a.[S NOB] as NOB, a.[S OAK] as OAK, a.[S TDC] as TDC, b.Stock_Plaspak as [3PL- Plaspak], b.Stock_Caratrans as [3PL- Caratrans], b.Stock_transit as [3PL- transit] from #stock1 a full outer join #3PL1 b on a.cono = b.co_num
union all
select 'Non-Stock: ' , GETDATE() , a.[NS MTL],a.[NS NOB], a.[NS OAK], a.[NS TDC], b.NS_Plaspak, b.NS_Caratrans, b.NS_transit from #stock1 a full outer join #3PL1 b on a.cono = b.co_num ) "a"
drop table #nStock
drop table #stock
drop table #3PL
drop table #3PL1
drop table #temp
drop table #stock1
END
On SQL Server 2014 I use the following code:
CREATE TABLE TempTable
(
LType varchar(255),
LStatus varchar(255),
PAmount decimal(16,2),
RAmount decimal(16,2));
INSERT INTO TempTable (LType, LStatus, PAmount, RAmount)
VALUES ('TypeA','StatusA', '1000', '10'),
('TypeB', 'StatusC', '500', '50'),
('TypeC', 'StatusB', '2500', '100'),
('TypeB', 'StatusB', '1000', '50'),
('TypeA', 'StatusA', '3000', '25'),
('TypeC', 'StatusB', '2200', '50');
Select Ltype, Lstatus, SUM(PAmount) as PAmount, SUM(RAmount) as RAmount
From TempTable
Where PAmount > 0
Group By LType, LStatus
to get this table:
What I’m trying to achieve is:
I used pivot but was unable to apply it simultaneously for PAmount and RAmount under Status columns.
Can anyone help with solution?
You can use conditional aggregation for this. This assumes you will always have these values. If you need this to be dynamic then there is a bit more work to do.
select StatusA_PAMount = max(case when Totals.Lstatus = 'StatusA' then Totals.PAmount end)
, StatusA_RAMount = max(case when Totals.Lstatus = 'StatusA' then Totals.RAmount end)
, StatusB_PAMount = max(case when Totals.Lstatus = 'StatusB' then Totals.PAmount end)
, StatusB_RAMount = max(case when Totals.Lstatus = 'StatusB' then Totals.RAmount end)
, StatusC_PAMount = max(case when Totals.Lstatus = 'StatusC' then Totals.PAmount end)
, StatusC_RAMount = max(case when Totals.Lstatus = 'StatusC' then Totals.RAmount end)
from
(
Select Lstatus
, SUM(PAmount) as PAmount
, SUM(RAmount) as RAmount
From TempTable
Where PAmount > 0
Group By LStatus
) Totals
I have code in the this following example.
legacy_id phone_type phone_number
1 f 1234567890
1 b 1233854100
1 f 4110256565
2 f 0707070770
2 b 7895120044
I want the data to end up like the following.
legacy_id f_phone_number_1 b_phone_number_1 f_phone_number_2
1 1234567890 1233854100 4110256565
2 0707070770 7895120044
My initial approach works but I was hoping there is a more efficient what of doing this.
Select fill.legacy_id, max(fill.f_phone_number_1),max(fill.b_phone_number_1),max(fill.f_phone_number_2)
from
(
Select
a.legacy_id as legacy_id, a.phone_type as phone_type,
case
when a.phone_type = 'F' then a.phone_number and
dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 1
else null
end as f_phone_number_1,
case
when a.phone_type = 'F' then a.phone_number and
dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 2
else null
end as f_phone_number_2,
case
when a.phone_type = 'b' then a.phone_number and
dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 1
else null
end as b_phone_number_1
from table a
group by a.legacy_id, a.phone_type, a.phone_number
) fill
group by fill.legacy_id
Is there a more efficient way of approaching this?
If you don't need to go dynamic, a conditional aggregation should do the trick
Declare #YourTable table (legacy_id int,phone_type varchar(25),phone_number varchar(25))
Insert Into #YourTable values
(1,'f','1234567890'),
(1,'b','1233854100'),
(1,'f','4110256565'),
(2,'f','0707070770'),
(2,'b','7895120044')
Select legacy_id
,f_phone_number_1 = max(case when phone_type='f' and RowNr=1 Then phone_number else '' end)
,b_phone_number_1 = max(case when phone_type='b' and RowNr=1 Then phone_number else '' end)
,f_phone_number_2 = max(case when phone_type='f' and RowNr=2 Then phone_number else '' end)
,b_phone_number_2 = max(case when phone_type='b' and RowNr=2 Then phone_number else '' end)
From (
Select *
,RowNr=Row_Number() over (Partition By legacy_id,phone_type Order By (Select NULL) )
From #YourTable
) A
Group By legacy_id
Returns
legacy_id f_phone_number_1 b_phone_number_1 f_phone_number_2 b_phone_number_2
1 4110256565 1233854100 1234567890
2 0707070770 7895120044
I'm struggling with this one. I have a table A which looks like this:
Employee_ID Dependant_FirstName DOB
1 John 12/12/1980
1 Lisa 11/11/1982
2 Mark 06/06/1985
2 Shane 07/07/1982
2 Mike 03/04/1990
3 NULL NULL
and would like to copy these data in Table B like this (knowing that there could only be a maximum of 6 dependants in Table A):
Employee_ID Dependant1_FirstName DOB Dependant2_FirstName DOB Dependant3_FirstName DOB
1 John 12/12/1980 Lisa 11/11/1982 NULL NULL
2 Mark 06/06/1985 Shane 07/07/1982 Mike 03/04/1990
3 NULL NULL NULL NULL NULL NULL
Thanks very much for the help.
Marc
This is a working example for just your example data, to give an idea of how I'd do it. I'm using a faked-up dependant counter based on date of birth and name. Bear in mind it will break if an employee has twins with the same name, but if they do that, then they deserve all the lifelong data-confusion that they've got in store :)
Also, please consider upgrading that SQL Server. Or moving this kind of pivoting to your reporting tool rather than the database.
CREATE TABLE #employees (employee_id INTEGER, Dependant_FirstName VARCHAR(20), DOB DATETIME)
INSERT INTO #employees VALUES (1, 'John', '12/12/1980')
INSERT INTO #employees VALUES (1, 'Lisa', '11/11/1982')
INSERT INTO #employees VALUES (2, 'Shane', '07/07/1982')
INSERT INTO #employees VALUES (2, 'Mark', '06/06/1985')
INSERT INTO #employees VALUES (2, 'Mike', '03/04/1990')
INSERT INTO #employees VALUES (3, NULL, NULL)
SELECT
employee_id,
MAX(CASE WHEN dep_count = 1 THEN Dependant_FirstName ELSE NULL END) 'Dependant1_FirstName',
MAX(CASE WHEN dep_count = 1 THEN DOB ELSE NULL END) 'Dependant1_DOB',
MAX(CASE WHEN dep_count = 2 THEN Dependant_FirstName ELSE NULL END) 'Dependant2_FirstName',
MAX(CASE WHEN dep_count = 2 THEN DOB ELSE NULL END) 'Dependant2_DOB',
MAX(CASE WHEN dep_count = 3 THEN Dependant_FirstName ELSE NULL END) 'Dependant3_FirstName',
MAX(CASE WHEN dep_count = 3 THEN DOB ELSE NULL END) 'Dependant3_DOB'
FROM
(
SELECT
employee_id,
Dependant_FirstName,
DOB,
(
SELECT
COUNT(*)
FROM
#employees deps
WHERE
#employees.employee_id = deps.employee_id AND
CONVERT(VARCHAR, #employees.DOB, 126) + #employees.Dependant_FirstName <=
CONVERT(VARCHAR, deps.DOB, 126) + deps.Dependant_FirstName
) 'dep_count'
FROM
#employees
) add_dep_count_query
GROUP BY
employee_id
You could
Create a view
Calculate a fictuous ranking
Group to find the maximum ranking for each employee_ID
return the results.
Note: I have ommitted the DOB column in the examples
Statement
CREATE VIEW dbo.VIEW_Employees_Ranking AS
SELECT Ranking = ISNULL(e6.Employee_ID, 0)
+ ISNULL(e5.Employee_ID, 0)
+ ISNULL(e4.Employee_ID, 0)
+ ISNULL(e3.Employee_ID, 0)
+ ISNULL(e2.Employee_ID, 0)
+ ISNULL(e1.Employee_ID, 0)
, e1.Employee_ID
, Name1 = e1.Dependant_FirstName
, Name2 = e2.Dependant_FirstName
, Name3 = e3.Dependant_FirstName
, Name4 = e4.Dependant_FirstName
, Name5 = e5.Dependant_FirstName
, Name6 = e6.Dependant_FirstName
FROM dbo.Employees e1
LEFT OUTER JOIN dbo.Employees e2 ON e2.Employee_ID = e1.Employee_ID AND e2.DOB > e1.DOB
LEFT OUTER JOIN dbo.Employees e3 ON e3.Employee_ID = e2.Employee_ID AND e3.DOB > e2.DOB
LEFT OUTER JOIN dbo.Employees e4 ON e4.Employee_ID = e3.Employee_ID AND e4.DOB > e3.DOB
LEFT OUTER JOIN dbo.Employees e5 ON e5.Employee_ID = e4.Employee_ID AND e5.DOB > e4.DOB
LEFT OUTER JOIN dbo.Employees e6 ON e6.Employee_ID = e5.Employee_ID AND e6.DOB > e5.DOB
GO
SELECT er.*
FROM dbo.VIEW_Employees_Ranking er
INNER JOIN (
SELECT Ranking = MAX(Ranking)
, Employee_ID
FROM dbo.VIEW_Employees_Ranking
GROUP BY
Employee_ID
) ermax ON ermax.Ranking = er.Ranking AND ermax.Employee_ID = er.Employee_ID
Check this code please, It might work for you.
declare #Emp_Id int
declare #Name int
declare #DOB int
declare #Count int
set #Count=1
DECLARE x_cursor CURSOR FOR
SELECT distinct Employee_ID from tableA
OPEN x_cursor
FETCH NEXT FROM x_cursor
INTO #Emp_Id
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE second_cursor CURSOR FOR
SELECT distinct Dependant_FirstName,DOB from tableA
where Employee_ID=#Emp_Id
OPEN second_cursor
FETCH NEXT FROM second_cursor
INTO #Name,#DOB
WHILE ##FETCH_STATUS = 0
BEGIN
if(#Count=1)
begin
insert into tableB (Employee_ID , Dependant1_FirstName,DOB)
values(#Emp_Id,#Name,#DOB)
set #Count=#Count+1
end
else
begin
exec('Update tableB set Dependant'+#count+'_FirstName='+#Name+' ,DOB'+#Count+'='+#DOB+' where Employee_ID='+#Emp_Id)
set #Count=#Count+1
end
FETCH NEXT FROM second_cursor
INTO #Name,#DOB
END
CLOSE second_cursor
DEALLOCATE second_cursor
set #Count=1
FETCH NEXT FROM x_cursor
INTO #Emp_Id
END
CLOSE x_cursor;
DEALLOCATE x_cursor
GO
Have a look at this example:
http://ryanfarley.com/blog/archive/2005/02/17/1712.aspx
here he is concatentating the child elements of a parent key into a string which should allow you to write out a flat record.