unpivot the table for single column - sql-server

I am trying to unpivot the table in sql but it's throwing an error. Help is appreciated
create table #test (id int ,GroupType varchar(50),State_NM varchar(20))
Insert Into #test values (100, 'Facility' ,'TX')
Insert Into #test values (100, 'Group' ,NULL)
Insert Into #test values (100, 'JobTitle' ,'TX')
Insert Into #test values (100, 'JobTitle' ,'NC')
Insert Into #test values (101, 'Facility' ,'NM')
Insert Into #test values (101, 'Group' ,'TX')
Insert Into #test values (102, 'Facility' ,'TX')
Insert Into #test values (102, 'Group' ,Null)
Insert Into #test values (102, 'Jobtitle' ,'CA')
select * from #test
SELECT ID, facility,Group,JobTitle FROM
(SELECT ID,GroupType,State_NM FROM #test )Tab1
PIVOT
(
State_NM FOR GroupType IN ([facility],[Group[,[JobTitle])) AS Tab2
ORDER BY Tab2.Name
Expected Result

with string_agg() to "feed" your pivot
Example or dbFiddle
Select *
From (
select id
,GroupType
,Value = string_agg(state_NM,',')
from #test
Group by id,groupType
) src
Pivot ( max(value) for GroupType IN ([facility],[Group],[JobTitle])) pvt
Results
id facility Group JobTitle
100 TX NULL TX,NC
101 NM TX NULL
102 TX NULL CA
UPDATE: <=2016 Version
Select *
From (
select id
,GroupType
,Value = stuff( (Select ',' +state_NM From #test Where ID=A.ID and GroupType=A.GroupType For XML Path ('')),1,1,'')
From #test A
Group By id,GroupType
) src
Pivot ( max(value) for GroupType IN ([facility],[Group],[JobTitle])) pvt

Related

Repeat the column value until value change in same column value

My table structure:
declare #TestTable as table
(
id int,
somedate date,
somevalue int
)
insert into #TestTable values
(1, '2019-01-01', 1000),
(2, '2019-01-02', null ),
(3, '2019-01-03', null),
(4, '2019-01-04', null ),
(5, '2019-01-05', 800),
(6, '2019-01-06', null),
(7, '2019-01-07', null),
(8, '2019-01-08', null),
(9, '2019-01-09', null),
(10, '2019-01-10', 700)
Repeat the column value until any change in value of column (somevalue).. Is it possible with window functions?
Required output:
You can achieve that by using window function as well.
try the following:
select id, somevalue, newvalue=max(somevalue) over (partition by c)
from
(
select id, somevalue
,c=count(somevalue) over (order by id)
from #testtable
) t
order by id;
Please find the demo here.
Try this below logic-
DEMO HERE
SELECT A.*,
(
SELECT somevalue
FROM #TestTable
WHERE id = (
SELECT MAX(id)
FROM #TestTable
WHERE id <= A.id
AND somevalue IS NOT NULL
)
) new_column
FROM #TestTable A
ORDER BY A.id
You can achieve this using COALESCE (Transact-SQL)
.
SELECT
[id]
, somedate
, COALESCE(somevalue,
(SELECT TOP (1) somevalue
FROM #TestTable AS p2
WHERE
p2.somevalue IS NOT NULL
AND p2.[id] <= p.[id] ORDER BY p2.[id] DESC))
FROM #TestTable AS p;
Here is the live db<>fiddle demo.

Unable to get desired output using Dense Rank

Can you please help me how to get the expected output as shown in the screenshot below?
DECLARE #TT TABLE ( CUSTOMERID INT, TYPE VARCHAR(100) , D1 DATE)
INSERT INTO #TT VALUES ( 15001,'TYPE1', '4/1/2017')
INSERT INTO #TT VALUES ( 15001,'TYPE1', '4/2/2017')
INSERT INTO #TT VALUES ( 15001,'TYPE1', '4/3/2017')
INSERT INTO #TT VALUES ( 15001,'NON TYPE1', '4/4/2017')
INSERT INTO #TT VALUES ( 15001,'NON TYPE1', '4/5/2017')
INSERT INTO #TT VALUES ( 15001,'NON TYPE1', '4/6/2017')
INSERT INTO #TT VALUES ( 245,'Non TYPE1', '4/1/2017')
INSERT INTO #TT VALUES ( 245,'Non TYPE1', '4/2/2017')
INSERT INTO #TT VALUES ( 245,'Non TYPE1', '4/3/2017')
INSERT INTO #TT VALUES ( 245,'TYPE1', '4/4/2017')
INSERT INTO #TT VALUES ( 245,'TYPE1', '4/5/2017')
INSERT INTO #TT VALUES ( 245,'TYPE1', '4/6/2017')
A query is:
SELECT * ,
DENSE_RANK() OVER ( PARTITION BY CUSTOMERID ORDER BY CUSTOMERID,TYPE) DR
FROM #TT
WHERE CUSTOMERID = 15001
ORDER BY CUSTOMERID,D1
SELECT *,
DENSE_RANK() OVER ( PARTITION BY CUSTOMERID ORDER BY CUSTOMERID,TYPE) DR
FROM #TT
WHERE CUSTOMERID = 245
ORDER BY CUSTOMERID,D1
Thank you for the help.
You want to order groups by the minimum date. I think it is something like this:
SELECT t.*,
DENSE_RANK() OVER ( PARTITION BY CUSTOMERID ORDER BY mind1, TYPE) DR
FROM (SELECT t.*, MIN(d1) OVER (PARTITION BY CUSTOMERID, TYPE) as mind1
FROM #TT t
) t
WHERE CUSTOMERID = 15001
ORDER BY CUSTOMERID, D1;
This sort of assumes that the types are not interleaved (as in your examples). If that is the case, then please ask another question. That significantly changes the question. That question should also provide better sample data and desired results.

How to SELECT specific characters using SQL in SQL server database

How can I select only information that start with a #?
I have a table with 5 columns and in one of the columns i.e. the comments column there is information like:
#2345 Changed by Mark
Paul changed ticket number #5923
Someone changed ticket number #5823 and #9333
#3555 is missing from the list, can only see #5789, #9000 and #4568
In the sample of 4 rows above, I want my select statement to return only ticket numbers as shown below:
comments
#2345
#5923
#5823, #9333
#5789, #9000, #4568
Someone said regular expressions can do the work for me but I am fresh graduate and have never seen such before. Can you help me please??
Select the required fields from your database table using SQL, then perform regex operations on the result in another language such as c++, php etc. when outputting your result to the client
First Create Function To extract #numeric values
CREATE FUNCTION dbo.udf_GetNumeric
(
#strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256
)
AS
BEGIN
DECLARE #intAlpha INT
SET #intAlpha = PATINDEX('%[^#0-9]%', #strAlphaNumeric)
BEGIN
WHILE #intAlpha > 0
BEGIN
SET #strAlphaNumeric = STUFF(#strAlphaNumeric, #intAlpha, 1, '' )
SET #intAlpha = PATINDEX('%[^#0-9]%', #strAlphaNumeric )
END
END
RETURN ISNULL(#strAlphaNumeric,0)
END
GO
By Using Below Code we can Extract the numeric values
Declare #TempTable TABLE(ID Int Identity,Value varchar(1000))
INSERT INTO #TempTable
SELECT '#2345 Changed by Mark'
UNION ALL SELECT 'Paul changed ticket number #5923'
UNION ALL SELECT 'Someone changed ticket number #5823 and #9333'
UNION ALL SELECT '#3555 is missing from the list, can only see #5789, #9000 and #4568'
SELECT ID,
RIGHT(LTRIM(REPLACE(Value,'#',' ,#')),LEN(RTRIM(LTRIM(REPLACE(Value,'#',' ,#'))))-1)AS Value FROM
(
SELECT ID,dbo.udf_GetNumeric(Value) AS Value From #TempTable
)Dt
If you need to extract Numeric values Instead of pre-fixed wirh '#' Symbol
SELECT ID,
REPLACE(RIGHT(LTRIM(REPLACE(Value,'#',' ,#')),LEN(RTRIM(LTRIM(REPLACE(Value,'#',' ,#'))))-1),'#',' ')AS Value FROM
(
SELECT ID,dbo.udf_GetNumeric(Value) AS Value From #TempTable
)Dt
OutPut
ID Value
----------
1 #2345
2 #5923
3 #5823 ,#9333
4 #3555 ,#5789 ,#9000 ,#4568
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
Drop table #TempTable
CREATE TABLE [dbo].#TempTable(
[ID] [int] NOT NULL,
[Value] [varchar](1000) NULL
) ON [PRIMARY]
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (1, N'#2345 Changed by Mark #111111,767677,33333,#5656 vbvb')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (2, N'Paul changed ticket number #5923,5555555 464646 #010101,5555544rrr,wwww AND #4 ')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (3, N'Someone changed ticket number #5823 and #9333,7777')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (4, N'#3555 is missing from the list, can only see #5789, #9000 and #4568')
GO
;WITH cte
AS
(
SELECT ID,Split.a.value('.', 'VARCHAR(1000)') AS TablesData
FROM (
SELECT ID,CAST('<S>' + REPLACE(Value, ' ', '</S><S>') + '</S>' AS XML) AS TablesData
FROM #TempTable
) AS A
CROSS APPLY TablesData.nodes('/S') AS Split(a)
)
,Final
AS
(
SELECT ID,TablesData FROM
(
SELECT ID, Split.a.value('.', 'VARCHAR(1000)') AS TablesData,CHARINDEX('#',Split.a.value('.', 'VARCHAR(1000)')) AS Data2
FROM (
SELECT ID,CAST('<S>' + REPLACE(TablesData, ',', '</S><S>') + '</S>' AS XML) AS TablesData
FROM cte
) AS A
CROSS APPLY TablesData.nodes('/S') AS Split(a)
)DT
WHERE dt.Data2 <>0
)
SELECT DISTINCT ID
,STUFF((
SELECT ', ' + CAST(TablesData AS VARCHAR(50))
FROM Final i
WHERE i.ID = o.ID
FOR XML PATH('')
), 1, 1, '') AS ColumnsWith#ValuesOnly
FROM Final o
ORDER BY 1 ASC
OutPut
ID ColumnsWith#ValuesOnly
---------------------------
1 #2345, #111111, #5656
2 #5923, #010101, #4
3 #5823, #9333
4 #3555, #5789, #9000, #4568
The best way is to use this script below:
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
Drop table #TempTable
CREATE TABLE [dbo].#TempTable(
[ID] [int] NOT NULL,
[Value] [varchar](1000) NULL
) ON [PRIMARY]
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (1, N'#2345 Changed by Mark #111111,767677,33333,#5656 vbvb')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (2, N'Paul changed ticket number #5923,5555555 464646 #010101,5555544rrr,wwww AND #4 ')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (3, N'Someone changed ticket number #5823 and #9333,7777')
GO
INSERT [dbo].#TempTable ([ID], [Value]) VALUES (4, N'#3555 is missing from the list, can only see #5789, #9000 and #4568')
GO
;WITH cte
AS
(
SELECT ID,Split.a.value('.', 'VARCHAR(1000)') AS TablesData
FROM (
SELECT ID,CAST('<S>' + REPLACE(Value, ' ', '</S><S>') + '</S>' AS XML) AS TablesData
FROM #TempTable
) AS A
CROSS APPLY TablesData.nodes('/S') AS Split(a)
)
,Final
AS
(
SELECT ID,TablesData FROM
(
SELECT ID, Split.a.value('.', 'VARCHAR(1000)') AS TablesData,CHARINDEX('#',Split.a.value('.', 'VARCHAR(1000)')) AS Data2
FROM (
SELECT ID,CAST('<S>' + REPLACE(TablesData, ',', '</S><S>') + '</S>' AS XML) AS TablesData
FROM cte
) AS A
CROSS APPLY TablesData.nodes('/S') AS Split(a)
)DT
WHERE dt.Data2 <>0
)
SELECT DISTINCT ID
,STUFF((
SELECT ', ' + CAST(TablesData AS VARCHAR(50))
FROM Final i
WHERE i.ID = o.ID
FOR XML PATH('')
), 1, 1, '') AS ColumnsWith#ValuesOnly
FROM Final o
ORDER BY 1 ASC

SQL Server query help - Related hashtags

I have been racking my brains on this one for some time, so through it was about time to ask for some help.
I have a product database, each product has a number of hashtags associated with it. I want to be able to pull out related hashtags.
Let me take you through an example:
CREATE TABLE #Test (ProductID int, Hashtag varchar(30))
INSERT INTO #Test VALUES( 1 ,'toys')
INSERT INTO #Test VALUES( 1 ,'lego')
INSERT INTO #Test VALUES( 1 ,'construction')
INSERT INTO #Test VALUES( 2 ,'toys')
INSERT INTO #Test VALUES( 2 ,'lego')
INSERT INTO #Test VALUES( 2 ,'lego-city')
INSERT INTO #Test VALUES( 3 ,'clothing')
INSERT INTO #Test VALUES( 3 ,'womens')
INSERT INTO #Test VALUES( 3 ,'jeans')
INSERT INTO #Test VALUES( 4 ,'clothing')
INSERT INTO #Test VALUES( 4 ,'mens')
INSERT INTO #Test VALUES( 4 ,'tops')
INSERT INTO #Test VALUES( 4 ,'t-shirts')
INSERT INTO #Test VALUES( 5 ,'clothing')
INSERT INTO #Test VALUES( 5 ,'mens')
INSERT INTO #Test VALUES( 5 ,'tops')
INSERT INTO #Test VALUES( 5 ,'vests')
What I want to be able to do is select a Hashtag, for example "toys", then pull out all other hashtags that have a relationship (via the productId).
This is the results set that should be returned when querying "toys":
hashtag, count
lego, 2
construction, 1
lego-city, 1
Any help or ideas on how to go about implementing this would be much appreciated.
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table YourTable
(
Product_id int,
hashtag varchar(25)
)
insert into YourTable values
( 1, 'toys '),
( 1, 'lego '),
( 1, 'construction '),
( 2, 'toys '),
( 2, 'lego '),
( 3, 'lego '),
( 2, 'lego-city ')
Query 1:
select T1.hashtag,
count(*) as [count]
from YourTable as T1
where exists (
select *
from YourTable as T2
where T2.hashtag = 'toys' and
T1.Product_id = T2.Product_id
) and
T1.hashtag <> 'toys'
group by T1.hashtag
Results:
| HASHTAG | COUNT |
|---------------|-------|
| construction | 1 |
| lego | 2 |
| lego-city | 1 |
try this
select hashtag,count(hashtag) as count from #product_hashtags group by hashtag
CREATE TABLE #Test (ProductID int, Hashtag varchar(30))
INSERT INTO #Test VALUES( 1 ,'toys')
INSERT INTO #Test VALUES( 1 ,'lego')
INSERT INTO #Test VALUES( 1 ,'construction')
INSERT INTO #Test VALUES( 2 ,'toys')
INSERT INTO #Test VALUES( 2 ,'lego')
INSERT INTO #Test VALUES( 2 ,'lego-city')
SELECT * FROM #Test
SELECT * FROM (
SELECT Hashtag, COUNT(ProductID) Counter FROM #Test
GROUP BY Hashtag) as x
where x.Hashtag <> 'toys'
Is this what you want?
Use the query below:
SELECT Hashtag, COUNT(Hashtag)
FROM #Test
WHERE ProductID IN (SELECT ProductID FROM #Test WHERE Hashtag = 'toys')
AND Hashtag <> 'toys'
GROUP BY Hashtag

Comparing two select statements

I need to write a stored procedure in T-SQL that would do the following:
Get a list of items related to a certain SectionID
Select and return all of the SectionIDs that have the same list of items or more (not less)
The table structure is as follows:
Section ID | Item Name
1 Item1
2 Item1
1 Item2
1 Item3
2 Item2
So if I pass 1 as an ID, this should not return anything as SectionID 2 only has 2 of the 3 items that SectionID = 1 has, but if I pass SectionID = 2 as the parameter, this should return SectionID = 1.
Hopefully, I explained that properly. What would be a good approach for this?
Here is a full example of what you need:
create table #test (
SectionID int,
ItemName varchar(10)
)
insert into #test values (1, 'Item1')
insert into #test values (2, 'Item1')
insert into #test values (1, 'Item2')
insert into #test values (1, 'Item3')
insert into #test values (2, 'Item2')
insert into #test values (3, 'Item1')
insert into #test values (3, 'Item2')
insert into #test values (3, 'Item3')
declare #test int
select #test = 3
declare #dist int
select #dist = count(distinct ItemName) from #test where SectionID = #test
select distinct t0.SectionID from #test t0
left join (select distinct SectionID, ItemName from #test where SectionID = #test) t1
on t0.ItemName = t1.ItemName and t0.SectionID != t1.SectionID
where t0.SectionID != #test
group by t0.SectionID
having count(distinct t1.ItemName) >= #dist
drop table #test
In your case you just need this part:
declare #test int
select #test = 3 --input argument from stored procedure
declare #dist int
select #dist = count(distinct ItemName) from tablename where SectionID = #test
select distinct t0.SectionID from tablename t0
left join (select distinct SectionID, ItemName from tablename where SectionID = #test) t1
on t0.ItemName = t1.ItemName and t0.SectionID != t1.SectionID
where t0.SectionID != #test
group by t0.SectionID
having count(distinct t1.ItemName) >= #dist
Assuming the following Table...
DECLARE #Sections AS TABLE (Id INT, Item VARCHAR(25))
INSERT INTO #Sections
(Id, Item)
SELECT 1, 'Item1'
UNION SELECT 2, 'Item1'
UNION SELECT 1, 'Item2'
UNION SELECT 1, 'Item3'
UNION SELECT 2, 'Item2'
You can do this...
DECLARE #SectionId INT, #ItemCount INT
SELECT #SectionId = 2 --You'd change this to whatever
, #ItemCount = 0
SELECT #ItemCount = COUNT(*)
FROM #Sections
WHERE Id = #SectionId
SELECT s.Id
FROM #Sections AS p
JOIN #Sections AS s
ON s.Id != p.Id
AND s.Item = p.Item
WHERE p.Id = #SectionId
GROUP BY s.Id
HAVING COUNT(*) >= #ItemCount

Resources