Pivot String SQL - sql

I am trying to Pivot this table whose name is #salida
IDJOB NAME DATE
1 Michael NULL
1 Aaron NULl
THe result which I want to obtain is
IDJOB DATE NAME1 NAME2
1 NULL Michael Aaron
My code is this
SELECT *
FROM #salida
PIVOT
(
MAX([Name]) FOR [Name] IN ([Name1],[Name2])
) PVT GROUP BY IdJob,Date,Name1,Name2 ;
SELECT * FROM #salida
The result which obtain is
IDJOB DATE NAME1 NAME2
1 NULL NULL NULL

#XabiIparra, see a mock up. you need to partition by the IdJob and then add the columns needed.
DECLARE #salida TABLE(idjob VARCHAR(100),[Name] VARCHAR(100),[DATE] DATE);
INSERT INTO #salida VALUES
(1,'Michael', NULL)
,(1,'Aaron', NULL)
,(2,'Banabas', NULL)
SELECT p.*
FROM
(
SELECT *
,'NAME'+CAST(ROW_NUMBER() OVER(PARTITION BY [idjob] ORDER BY NAME) AS varchar(100)) ColumnName
FROM #salida
)t
PIVOT
(
MAX([Name]) FOR ColumnName IN (NAME1,NAME2,NAME3,NAME4,NAME5 /*add as many as you need*/)
)p;

How about must using aggregation and min() and max()?
select idjob, date, min(name), max(name)
from #salida
group by idjob, date;
SQL tables represent unordered sets, so there is no ordering to the values (unless another column specifies the ordering). So, this is probably the simplest way to get two different values in the same row.

Related

is possible to unpivot a sql server table using headers as a column and values as another column?

I have a table like this:
TableName
dates
ModelName
BaseUnitPerPallet
pallet
Calendar
June
Null
4
1
Country
June
Null
2
6
Product
June
DOWNSTREAM
Null
8
ProductBOM
June
DOWNSTREAM
9
9
and I want a table like this:
Columns
values
TableName
Calendar
TableName
Country
TableName
Product
TableName
ProductBOM
where columns field is the headers of the previous table, and values are the values in an unpivot way.
I have been trying without success the unpivot logic:
SELECT Columns, Values
FROM
(
SELECT TableName, dates, ModelName, BaseUnitPerPallet, pallet
FROM Database
as source_query
)
UNPIVOT
(
Values FOR Columns IN ( TableName, dates, ModelName, BaseUnitPerPallet, pallete)
)
as pivot_results
any advice or guidance would be great.
Additionally, any resource to do this dinamic? and apply the logic without write the column names?
Thanks in advanceĀ”
I'd recommend using APPLY to unpivot your table
Unpivot using APPLY
DROP TABLE IF EXISTS #YourTable
CREATE TABLE #YourTable (
ID INT IDENTITY(1,1) PRIMARY KEY
,TableName VARCHAR(100)
,Dates Varchar(25)
,ModelName VARCHAR(100)
,BaseUnitPerPallet TINYINT
,Pallet TINYINT
)
INSERT INTO #YourTable
VALUES
('Calendar','June',NULL,4,1)
,('Country','June',NULL,2,6)
,('Product','June','DOWNSTREAM',NULL,8)
,('ProductBOM','June','DOWNSTREAM',9,9)
SELECT A.ID,B.*
FROM #YourTable AS A
CROSS APPLY
(VALUES
('TableName',A.TableName)
,('Dates',A.Dates)
,('ModelName',A.ModelName)
,('BaseUnitPerPallet',CAST(A.BaseUnitPerPallet AS Varchar(100)))
,('Pallet',CAST(A.Pallet AS Varchar(100)))
) AS B(ColumnName,Val)
--WHERE B.Val IS NOT NULL /*Optional in case you want to ignore NULLs*/
ORDER BY A.ID,B.ColumnName

select string between 3rd and 4th pipe delimiter

I have a column that contains values such as
Column
Asset|Class1|Category1|Group1|Account1
Expense|Class23|Category23|Group23|Account23
I want to select the string between 3rd and 4th occurrence of my pipe delimiter, how can I achieve this?
I've tried the PARSENAME and charindex+stuff function, but they have limitations, like max 128 characters. Also our SQL server has limited regex support. Any ideas?
SELECT REVERSE(PARSENAME(REVERSE(replace(LTRIM(Column), '|', '.')), 3))
My select need to return:
Group1
Group23
Perhaps this will help
Example
Declare #YourTable table (ID int,[Column] varchar(max))
Insert Into #YourTable values
(1,'Asset|Class1|Category1|Group1|Account1')
,(2,'Expense|Class23|Category23|Group23|Account23')
Select ID
,SomeValue = convert(xml,'<x>' + replace([Column],'|','</x><x>')+'</x>').value('/x[3]','varchar(100)')
From #YourTable
Returns
ID SomeValue
1 Category1
2 Category23
You can also use STRING_SPLIT() if you have 2016+
CREATE TABLE T(
ID INT IDENTITY(1,1),
Str VARCHAR(45)
);
INSERT INTO T(Str) VALUES
('Asset|Class1|Category1|Group1|Account1'),
('Expense|Class23|Category23|Group23|Account23');
SELECT V Str
FROM (
SELECT Value V,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID) RN
FROM T CROSS APPLY STRING_SPLIT(Str, '|')
) TT
WHERE RN = 3;
Returns:
Str
---------
Category1
Category23

How to get the each record with some condition

I have following data:
DECLARE #temp TABLE (
ID int
,sn varchar(200)
,comment varchar(2000)
,rownumber int
)
insert into #temp values(1,'sn1',NULL,1)
insert into #temp values(2,'sn1','aaa',2)
insert into #temp values(3,'sn1','bbb',3)
insert into #temp values(4,'sn1',NULL,4)
insert into #temp values(5,'sn2',NULL,1)
insert into #temp values(6,'sn2',NULL,2)
insert into #temp values(7,'sn2',NULL,3)
select * from #temp
And I want to output like this:
2 sn1 aaa 2
5 sn2 NULL 1
same sn, if comment have value, get this lower rownumber's record. For sn1, have two records with comment value, so here, get the the record with rownumber=2
If comment doesn't have value, get the lower rownumber's record. For sn2, get the record with rownumber=1
May I know how to write this SQL?
This is a prioritization query. I think row_number() is the simplest method:
select t.*
from (select t.*,
row_number() over (partition by sn
order by (case when comment is not null then 1 else 2 end),
rownumber
) as seqnum
from #temp t
) t
where seqnum = 1;
Here is a db<>fiddle.

Get the Records as per the given OrderId only

I have a table with Primary key and auto incremented column lets say "HeaderFieldID".
Now i want to get the records as per the HeaderFieldID values.
Ex:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
But,by default I am getting the records by HeaderFieldID asc order. But I want records as per the given HeaderFieldID's only.
Original Table
HeaderFieldID HFName DisplayName
1 OrgName1 disp1
2 OrgName2 disp2
3 OrgName3 disp3
4 OrgName4 disp4
5 OrgName5 disp5
6 OrgName6 disp6
Thanks in Advance
I don't know if you can order by IN, because you don't know order.
So first I would split data into rows from IN and then join it to your table.
DECLARE #table TABLE (ID INT IDENTITY(1,1) NOT NULL, NR INT)
--Prodvide data to lookup
DECLARE #givenText VARCHAR(100) = '2,1,3,4,5,6,7,8,9,10,11,12,13,14,15'
-- Split requested string into rows and add unique number
;WITH xmlData (xmlData) AS (
SELECT CAST('<x>'+REPLACE(#givenText, ',', '</x><x>')+'</x>' AS XML) AS xmlData
)
INSERT INTO #table (NR)
SELECT x.value('.','INT') AS NR
FROM xmlData
CROSS APPLY xmlData.xmlData.nodes('//x') AS func(x)
--Join tables to get result
SELECT tHF.*
FROM tblHeaderField AS tHF
INNER JOIN #table AS T
ON T.NR = tHF.HeaderFieldID
ORDER BY T.ID
Isn't clear where does this list come from (as a parameter of a stored procedure or hardcoded in the SQL statement?). Try this query:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
ORDER BY
CHARINDEX(','+CAST(HeaderFieldID as varchar(100))+','
,',2,1,3,4,6,5,')
SQLFiddle demo
I have solved my query.
SELECT * FROM tblHeaderField
WHERE HeaderFieldID in (5,6,2,1,3,4,7,8,9,10,11,12,13,14,15)
ORDER BY CHARINDEX(CAST(HeaderFieldID AS VARCHAR), '5,6,2,1,3,4,7,8,9,10,11,12,13,14,15')

How can I order data and add a record to the first position of the data set?

I know I can create a temp table, insert records, order it and then use union afterwards, but I'm looking for alternative routes. I tried a cte, but I had to order the entire thing which doesn't work as my unioned record doesn't stay "on top".
Basically, I have at able with Id INT, Name VARCHAR(MAX) fields and I want to ORDER BY Name before I add an entry at the row[0] position in the return set. If I order after the union, the row I wanted at row[0] gets ordered with it.
Any ideas?
You were on the right track with a union query. Force the sort with static values.
select 0 sortfield, '' name, etc
union
select 1 sortfield, name, etc
from etc
order by sortfield, name.
CREATE TABLE #temp (
idnt INT IDENTITY(2) NOT NULL --This begins the identity col with a value of 2
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #temp
SELECT
...
FROM myTable
ORDER BY Name
CREATE TABLE #tempAPPEND (
idnt INT IDENTITY(1) NOT NULL --This begins the identity col with a value of 1
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #tempAPPEND (Id, Name)
VALUES ('34384','Pinal Dave') -- SAMPLE VALUES
SELECT * FROM #temp
UNION
SELECT * FROM #tempAPPEND
ORDER BY idnt