Trim off parenthesized text from columns that have it? - sql

I have an NVARCHAR(80) column. Some column values end with a space, followed by a number within parentheses. (As shown below.)
Is there a SQL-Server syntax to remove the space, parentheses, and number from values that have them, but leave all other values unchanged?
For example, "SANDFRAC4070 (1441316)" would become "SANDFRAC4070", and "SAND FRACING 30 50 MESH" would be unchanged.
Sample Data
SAND FRACING 100 MESH (1441317)
SAND FRACING 100 MESH (1441317)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC4070 (1441316)
SANDFRAC3050MES
SANDFRAC3050MES
SANDFRAC3050MES
SANDFRAC3050MES
SANDFRAC4070MES
SANDFRAC4070MES
SANDFRAC4070MES
SANDFRAC4070MES
SANDFRAC4070MES
SANDFRAC4070MES
SANDFRAC4070MES
SAND FRACING 30 50 MESH
SAND FRACING 30 50 MESH

One option is charindex() with a "Fail-Safe"
Example
Declare #YourTable Table ([SomeCol] varchar(50)) Insert Into #YourTable Values
('SANDFRAC4070 (1441316)')
,('SANDFRAC3050MES')
Select *
,left(SomeCol,charindex(' (',SomeCol+' (')-1)
From #YourTable
Results
SomeCol (No column name)
SANDFRAC4070 (1441316) SANDFRAC4070
SANDFRAC3050MES SANDFRAC3050MES

Related

Row values check in consecutive rows using SQL Server

I have a data set as below. I want to check the row values consecutive in L/P column one by one .
As an example for the tradedate between 2019-02-12 and 2019-02-14 L/P return values were 1 0 0. for that same pattern there were records for tradedate between 2019-02-16 and 2019-02-18.
How do I check that same pattern in L/P column using SQL Server?
tradedate price lost / profit L/P
---------- ----- ------------ ----
2019-02-11 150.00 0.00 1
2019-02-12 330.00 180.00 1
2019-02-13 329.00 -1.00 0
2019-02-14 151.00 -178.00 0
2019-02-15 148.00 -3.00 0
2019-02-16 329.00 181.00 1
2019-02-17 326.00 -3.00 0
2019-02-18 146.00 -180.00 0
The DDL statement for table creation
CREATE TABLE dbo.Ticker
(
symbol VARCHAR(10) NOT NULL,
tradedate DATE NOT NULL,
price NUMERIC(12, 2) NOT NULL,
CONSTRAINT PK_Ticker
PRIMARY KEY (symbol, tradedate)
);
GO
INSERT INTO dbo.Ticker(symbol, tradedate, price)
VALUES
('STOCK1', '20190211', 150.00),
('STOCK1', '20190212', 330.00),
('STOCK1', '20190213', 329.00),
('STOCK1', '20190214', 151.00),
('STOCK1', '20190215', 148.00),
('STOCK1', '20190216', 329.00),
('STOCK1', '20190217', 326.00),
('STOCK1', '20190218', 146.00);
SQL query for getting above data set
SELECT
tradedate,
price,
((LAG(price, 1, price) OVER (ORDER BY tradedate)) - price) * -1 AS 'lost / profit',
CASE WHEN ((LAG(price, 1, 0) OVER (ORDER BY tradedate)) - price) < 0 THEN 1 ELSE 0 END AS 'L / P'
FROM
Ticker t
WHERE
tradedate BETWEEN '2019-02-11' AND '2019-02-18'
````
Try using a aggregate function like STRING_AGG():
(UPDATED):
SELECT
STRING_AGG([L / P], ' ')
FROM
(SELECT tradedate
,price
,((LAG(price, 1, price) OVER (ORDER BY tradedate)) - price) * -1 AS 'lost / profit'
,CASE WHEN ((LAG(price, 1, 0) OVER (ORDER BY tradedate)) - price) < 0 THEN 1 ELSE 0 END AS 'L / P'
FROM Ticker t
WHERE tradedate BETWEEN '2019-02-12' AND '2019-02-14')
EXCEPT
SELECT
STRING_AGG([L / P], ' ')
FROM
(SELECT tradedate
,price
,((LAG(price, 1, price) OVER (ORDER BY tradedate)) - price) * -1 AS 'lost / profit'
,CASE WHEN ((LAG(price, 1, 0) OVER (ORDER BY tradedate)) - price) < 0 THEN 1 ELSE 0 END AS 'L / P'
FROM Ticker t
WHERE tradedate BETWEEN '2019-02-16' AND '2019-02-18')

Retrieving distinct values and a count on duplicates in SQL

We have a table, lets call it "source-table", from where I retrieve these columns like this;
ANr, TNr, Type, IDate, EDate
1132173, 113615, Bogus, 2017-09-11 13:01:00, 2017-09-13 14:10:00
1132145, 184210, Triss, 2017-09-11 13:05:00, 2017-09-13 14:10:00
1131828, 259858, Bogus, 2017-09-11 13:11:00, 2017-09-13 14:10:00
1131844, 259858, Bogus, 2017-09-11 13:11:00, 2017-09-13 14:10:00
The above result is going to a new table called "export-table" and I then want to do a select from a third table, "info-table" but only with those just inserted in "export-table" and with a Count on how many duplicated entries if any (besides Anr which always is unique)
With the select mention above I want the following result:
Customernr, ANr, IDate, Type, Amount
703524, 1132173,2017-09-11 13:01:00, Bogus, 1
756899, 1132145,2017-09-11 13:05:00, Triss, 1
356658, 1131828,2017-09-11 13:11:00, Bogus, 2
Customernr comes from the "info-table", which has ANr as unique key.
As you can see the last two rows from "source-table" is identical besides Anr, but I need Anr later to get correct values from "info-table". It might work without Anr, if I can do a search on "info-table" with both Tnr and IDate, but I'll get duplicate entries there as well so not sure if that helps.
If someone wonder why the "export-table", then it is a kind of fail-safe so I wont export same stuff more than once.
I've been searching but since it is a bit complex question I haven't found a complete solution or any good hints.
how you did not put the customer, the best I can help you is
DECLARE #t table
(
ANr int
,TNr int
, Type varchar(10)
, IDate datetime
, EDate Datetime
)
insert #t (ANr, TNr, Type, IDate, EDate) values
(1132173, 113615, 'Bogus', '2017-09-11 13:01:00', '2017-09-13 14:10:00')
,(1132145, 184210, 'Triss', '2017-09-11 13:05:00', '2017-09-13 14:10:00')
,(1131828, 259858, 'Bogus', '2017-09-11 13:11:00', '2017-09-13 14:10:00')
,(1131844, 259858, 'Bogus', '2017-09-11 13:11:00', '2017-09-13 14:10:00')
Select Distinct
TNr
,IDate
,Type
,COUNT(1) OVER (PARTITION BY TNr, Type, IDATE)
from #t
Result
TNr IDate Type
----------- ----------------------- ---------- -----------
113615 2017-09-11 13:01:00.000 Bogus 1
184210 2017-09-11 13:05:00.000 Triss 1
259858 2017-09-11 13:11:00.000 Bogus 2
You can query as below:
Select top (1) with ties ANr, Idate, [Type], Count(*) over(partition by TNr, [Type], Idate) from
#sourcetable
order by row_number() over(partition by TNr, [Type], Idate order by Anr)
But not sure how you got Customernr
Output as below:
+---------+-------------------------+-------+--------+
| ANr | Idate | Type | Amount |
+---------+-------------------------+-------+--------+
| 1132173 | 2017-09-11 13:01:00.000 | Bogus | 1 |
| 1132145 | 2017-09-11 13:05:00.000 | Triss | 1 |
| 1131828 | 2017-09-11 13:11:00.000 | Bogus | 2 |
+---------+-------------------------+-------+--------+
You can use sub query for getting row_number as below
Select * from (
Select ANr, Idate, [Type], Amount = Count(*) over(partition by TNr, [Type], Idate)
,RowN = row_number() over(partition by TNr, [Type], Idate order by Anr)
from #sourcetable ) a
Where a.RowN = 1
DECLARE #t TABLE(ANr int, TNr int, Type NVARCHAR(100), IDate DATETIME, EDate DATETIME);
INSERT INTO #t VALUES
(1132173, 113615, 'Bogus', '2017-09-11 13:01:00', '2017-09-13 14:10:00')
,(1132145, 184210, 'Triss', '2017-09-11 13:05:00', '2017-09-13 14:10:00')
,(1131828, 259858, 'Bogus', '2017-09-11 13:11:00', '2017-09-13 14:10:00')
,(1131844, 259858, 'Bogus', '2017-09-11 13:11:00', '2017-09-13 14:10:00');
SELECT MIN(ANr) ANr, TNr, IDate, EDate, COUNT(*) AS Anz
FROM #t
GROUP BY TNr, IDate, EDate

Grouping Result Min/Max in a breaking series ascending/descending order in SQL

I want to select Min and Max in a ascending/descending order series if series breaks the data order
suppose I have data in a order by DateTime :
LogDate StartValue EndValue Multiplier DiffValue
2016-02-08 7661.25 7677.62 6.94 16.37
2016-02-09 7677.62 7693.02 6.94 15.4
2016-02-10 7693.02 7709.82 6.94 16.8
2016-02-11 7709.82 7727.08 6.94 17.26
2016-02-12 7727.08 7740.93 6.94 13.85
2016-02-13 3.02 12.22 6.94 9.2
2016-02-14 12.22 20.73 6.94 8.51
2016-02-15 20.73 37.04 6.94 16.31
2016-02-16 37.04 52.56 7 15.52
2016-02-17 52.56 67.82 7 15.26
2016-02-18 67.82 83.66 7 15.84
2016-02-19 83.66 98.77 7 15.11
2016-02-20 98.77 108.37 7 9.61
And I want the result Like :
LogDateMin LogDateMax StartValue EndValue Multiplier SumOfDiffValue
2016-02-08 2016-02-12 7661.25 7740.93 6.94 79.68
2016-02-13 2016-02-15 3.02 37.04 6.94 34.02
2016-02-16 2016-02-20 37.04 108.37 7 71.34
here I am grouping the result by Multiplier also and getting sum of deffValue
How can we achieve this
Please help
If I understood correctly, "break" means a minimum value threshold between the values as time flows.
In order to obtain the results, I have used LEAD and LAG functions to find the breaks, as they provide value before and after current record without using self JOIN.
Then, I have created the groups that contain only the first and last record near the "break". The resultset contains dates and values as rows, so an UNPIVOT is required.
The final query should look like this:
declare #Threshold NUMERIC(18, 2) = 1000
;with DeltaCte as (
SELECT DateTime, CurrValue,
LAG(CurrValue, 1, CurrValue - #Threshold - 1) OVER (ORDER BY DateTime) AS PrevVal,
LEAD(CurrValue, 1, CurrValue - #Threshold - 1) OVER (ORDER BY DateTime) AS NextVal
FROM RawData
)
,GroupsCTE AS (
select DateTime, CurrValue, CurrValue - PrevVal AS Delta1, CurrValue - NextVal AS Delta2,
(ROW_NUMBER() OVER (ORDER BY DateTime) + 1) / 2 AS GroupNo
FROM DeltaCte
WHERE ABS(CurrValue - PrevVal) > #Threshold OR ABS(CurrValue - NextVal) > #Threshold
)
SELECT GroupNo, MIN(d) AS DateTimeMin, MAX(d) DateTimeMax,
MIN(v) AS CurrValueMin, MAX(v) CurrValueMax
from GroupsCTE
UNPIVOT (v FOR nValue IN ([CurrValue])) AS P1
UNPIVOT (d FOR nDate IN ([DateTime])) AS P2
GROUP BY GroupNo
[EDIT]
If "break" means break of ascending order, above query becomes slightly simpler:
;with DeltaCte as (
SELECT DateTime, CurrValue,
LAG(CurrValue, 1, CurrValue + 1) OVER (ORDER BY DateTime) AS PrevVal,
LEAD(CurrValue, 1, CurrValue - 1) OVER (ORDER BY DateTime) AS NextVal
FROM RawData
)
,GroupsCTE AS (
select DateTime, CurrValue, CurrValue - PrevVal AS Delta1, CurrValue - NextVal AS Delta2, (ROW_NUMBER() OVER (ORDER BY DateTime) + 1) / 2 AS GroupNo
FROM DeltaCte
WHERE (CurrValue - PrevVal < 0) OR (NextVal - CurrValue < 0)
)
SELECT GroupNo, MIN(d) AS DateTimeMin, MAX(d) DateTimeMax,
MIN(v) AS CurrValueMin, MAX(v) CurrValueMax
from GroupsCTE
UNPIVOT (v FOR nValue IN ([CurrValue])) AS P1
UNPIVOT (d FOR nDate IN ([DateTime])) AS P2
GROUP BY GroupNo
Basically, delta to threshold comparison is replaced with delta to 0 comparison.

Creating a complex pivot table in T-SQL

I am using SQL Server 2008 R2 and T-SQL. These are abbreviated examples.
My table/view has the following fields
Table/View
ReportID,
UnitName,
UnitID,
CaseDefinitionID,
CaseDefinition,
DateOfDelivery,
YEAR(DateOfDelivery) AS [Year],
MONTH(DateOfDelivery) AS [Month],
DATENAME(m,DateOfDelivery) AS [Month name]
and my target report is:
Unit | Case type 1| Case type 2| Case total|
Unit A | 36| 40| 76|
2013| 20| 18| 38|
Jan| 10|
Feb| 10|
2014| 16|
Mar| 8|
Dec| 8|
Unit B | 12|
2013| 12|
Jan| 6|
May| 6|
Grand total| 48|
The month rows can be empty, NULL content is fine. The example report is incomplete to aid clarity.
Progress so far is the following query:
SELECT *
FROM
(
SELECT
PCT.[Year],
PCT.UnitName AS [Unit],
PCT.UnitID,
PCT.CaseDefinition AS [Case definition]
FROM
PivotBase AS PCT
) AS P1
PIVOT
(
COUNT(UnitID)
FOR [Case definition] IN ([Case type 1],[Case type 2])
) AS P2
This produces the following table
Year|Unit |Case type 1|Case type 2|
2013|Unit A | 20 | 18|
2014|Unit A | 16 | 22|
2013|Unit B | 6 | 8|
2014|Unit B | 6 | 8|
There is no need for dynamic SQL
My reading so far has covered many options but I still have no idea where to go next. How do I produce the required report.
You can get there by pivoting on Month and Year and then using WITH ROLLUP
WITH data
AS (SELECT *
FROM (SELECT Dateadd(month, Datediff(month, 0, PCT.dateofdelivery), 0
)
MonthYear,
PCT.unitid,
PCT.unitname
AS
[Unit],
PCT.casedefinition
AS
[Case definition]
FROM pivotbase AS PCT) AS P1
PIVOT ( Count(unitid)
FOR [case definition] IN ([Case type 1],
[Case type 2]) ) AS p2),
rollup
AS (SELECT Month(monthyear) Month,
unit unitX,
Year(monthyear) Year,
Sum([case type 1]) [case type 1],
Sum([case type 2]) [case type 2],
Grouping(unit) GUnit,
Grouping(Month(monthyear)) gm,
Grouping(Year(monthyear)) gy
FROM data
GROUP BY unit,
Year(monthyear),
Month(monthyear) WITH rollup)
SELECT COALESCE(Cast(month AS VARCHAR), Cast(year AS VARCHAR), unitx,
'Grand Total')
Unit,
[case type 1],
[case type 2]
FROM rollup
ORDER BY gunit,
unitx,
year,
gm DESC,
month
SQLFiddle
It's doable with some fancy rollup (SQL Fiddle)
;WITH
CTE1 AS
(
SELECT UnitName,
[Year],
[Month],
CaseDefinition,
GROUPING_ID(UnitName,[Year],[Month],CaseDefinition)
AS GroupingID,
CASE GROUPING_ID(CaseDefinition,UnitName,[Year],[Month])
WHEN 0 THEN UnitName + '-' + CAST(Year AS varchar(4)) + '-' + RIGHT('0' + CAST([Month] AS varchar(10)),2)
WHEN 1 THEN UnitName + '-' + CAST(Year AS varchar(4))
WHEN 3 THEN UnitName
WHEN 7 THEN 'zzz' -- So that grand total appears at the bottom
ELSE NULL
END AS GroupingLevel,
CASE GROUPING_ID(CaseDefinition,UnitName,[Year],[Month])
WHEN 0 THEN ' ' + CASE [Month]
WHEN 1 THEN 'Jan'
WHEN 2 THEN 'Feb'
WHEN 3 THEN 'Mar'
WHEN 4 THEN 'Apr'
WHEN 5 THEN 'May'
WHEN 6 THEN 'Jun'
WHEN 7 THEN 'Jul'
WHEN 8 THEN 'Aug'
WHEN 9 THEN 'Sep'
WHEN 10 THEN 'Oct'
WHEN 11 THEN 'Nov'
WHEN 12 THEN 'Dec'
END
WHEN 1 THEN ' ' + CAST([Year] AS varchar(4))
WHEN 3 THEN UnitName
WHEN 7 THEN 'Grand Total'
END AS DisplayName,
COUNT(UnitID) AS UnitCount
FROM PivotBase
GROUP BY GROUPING SETS(
(CaseDefinition),
(UnitName,CaseDefinition),
(UnitName,[Year],[CaseDefinition]),
(UnitName,[Year],[Month],CaseDefinition)
)
)
SELECT pvt.GroupingLevel,
pvt.DisplayName,
pvt.[Case Type 1],
pvt.[Case Type 2],
ISNULL(pvt.[Case Type 1],0) + ISNULL(pvt.[Case Type 2],0) AS [Case Total]
FROM CTE1
PIVOT (
SUM(UnitCount) FOR CaseDefinition IN ([Case Type 1],[Case Type 2])
) pvt
ORDER BY GroupingLevel
Explanation:
GROUPING SET( (set1), (set2), (set3) ) defines the roll up level. You will get a count of UnitID for each unique combination inside set1, then set2, then set3
GROUPING_ID is the most obscure function in here. Think of it as a bit mask. If a column is aggregated, its bit value is set to 1. For example: GROUPING_ID(field3, field2, field1, field0). If all 4 are not aggregated, the bit mask is 0000 = 0. If field0 is aggregated away, the returned value is 0001 = 1, and so on.
You can replace the last SELECT with SELECT * FROM CTE1 to see the inner working of the query.

SQL Query assistance using Pivot

I have a table as follows:
PriorityText Priority LoRes Partial Unknown N_A HiRes
------------------------------------------------------------------
Very High 5 0.0612 0.0000 0.0612 0.0612 0.2041
High 4 0.1429 0.0000 0.1633 0.0000 0.1633
Medium 3 0.0000 0.0000 0.1020 0.0000 0.0408
Low-Medium 2 0.0000 0.0000 0.0000 0.0000 0.0000
Low 1 0.0000 0.0000 0.0000 0.0000 0.0000
I am tying to transpose the tbale into this:
PriorityText Low Low-Medium Medium High Very High
--------------------------------------------------------
Priority 1 2 3 4 5
LoRes 0 0 0 0.1429 0.0612
Partial 0 0 0 0 0
Unknown 0 0 0.102 0.1633 0.0612
N_A 0 0 0 0 0.0612
HiRes 0 0 0.0408 0.1633 0.2041
I am using SQL 2008. I am habing trouble coming up with the SQL syntax to perform a pivot on the data.
Can someone please share a SQL snippet that will solve this for me?
I have used the following to successfully pivot one row, but I do not know how to make it do all my rows.
SELECT VeryHigh AS VeryHigh,
High AS High,
Medium AS Medium,
[Low-Medium] AS [Low-Medium],
Low AS Low
FROM (SELECT [PriorityText], [LoRes], [Low-Medium], [Medium], [High], [VeryHigh]
FROM #tbTemp) p
PIVOT (SUM(LoRes) FOR [PriorityText] in ([VeryHigh], [High], [Medium], [Low-Medium], [Low])) pvt
My test data in my table is as follows:
Priority PriorityText LoRes Partial Unknown N_A HiRes
1 VeryHigh 0.05 11 54 0 9
2 High 0.14 22 54 0 3
3 Medium 0.07 33 65 0 7
4 Low-Medium 0.01 44 87 0 4
5 Low 0 55 9 0 0
NULL NULL NULL NULL NULL NULL NULL
Thank for any help!!
You need to UNPIVOT data and then re-PIVOT values using desired column heads:
SELECT pvt.*
FROM
(
SELECT unpvt.PriorityText
,unpvt.PriorityText2
,unpvt.MyValueMyValue
FROM SourceTable src
UNPIVOT( MyValueMyValue FOR PriorityText2 IN ([Priority],[LoRes],[Partial],[Unknown],[N_A],[HiRes]) ) unpvt
) src2
PIVOT( MAX(src2.MyValueMyValue) FOR src2.PriorityText IN ([Low],[Low-Medium],[Medium],[High],[Very High]) ) pvt
This solution is kind of ugly, but i think it will do what you are asking for and is pretty straight forward.
There are more elegant and dynamic ways to transpose data with dynamic sql and with xml.
for example http://sql-tricks.blogspot.com/2011/04/sql-server-rows-transpose.html
-- POPULATE SAMPLE DATA
DECLARE #tbTemp table (PriorityText varchar(50), Priority float, LoRes float, Partial float, Unknown float, N_A float, HiRes float)
insert into #tbTemp (PriorityText,Priority,LoRes,Partial,Unknown,N_A, HiRes)
values
('Very High',5,0.0612,0.0000,0.0612,0.0612,0.2041),
('High',4,0.1429,0.0000,0.1633,0.0000,0.1633),
('Medium',3,0.0000,0.0000,0.1020,0.0000,0.0408),
('Low-Medium',2,0.0000,0.0000,0.0000,0.0000,0.0000),
('Low',1,0.0000,0.0000,0.0000,0.0000,0.0000)
;
with sourcetable ([Key],ColumnName,Value) -- Transposing into key/value-pair for each column
as
(
select 'Priority', PriorityText, Priority from #tbTemp
union all
select 'LoRes', PriorityText, LoRes from #tbTemp
union all
select 'Partial', PriorityText, Partial from #tbTemp
union all
select 'Unknow', PriorityText, Unknown from #tbTemp
union all
select 'N_A', PriorityText, N_A from #tbTemp
union all
select 'HiRes', PriorityText, HiRes from #tbTemp
)
select
grouptable.PriorityText,
(select Value from sourcetable
where sourcetable.ColumnName = 'Low'
and sourcetable.[Key] = grouptable.PriorityText) as Low,
(select Value from sourcetable
where sourcetable.ColumnName = 'Low-Medium'
and sourcetable.[Key] = grouptable.PriorityText) as [Low-Medium],
(select Value from sourcetable
where sourcetable.ColumnName = 'Medium'
and sourcetable.[Key] = grouptable.PriorityText)as Medium,
(select Value from sourcetable
where sourcetable.ColumnName = 'High'
and sourcetable.[Key] = grouptable.PriorityText) as High,
(select Value from sourcetable
where sourcetable.ColumnName = 'Very High'
and sourcetable.[Key] = grouptable.PriorityText) as [Very High]
from (
select 'Priority' as PriorityText
union all
select 'LoRes' as PriorityText
union all
select 'Partial' as PriorityText
union all
select 'Unknow' as PriorityText
union all
select 'N_A' as PriorityText
union all
select 'HiRes' as PriorityText
) grouptable -- Creating each row