Blanks rows exported from SQL to excel - sql-server

When I export my query to excel .CSV I get a blank line after a filled line.
How can I delete the blank line in my query so that it is not exported to excel
exmaple of outcome
SELECT
ID,
CASE
WHEN PATINDEX('%[0-9]%', q.outcome) <> 0
THEN SUBSTRING(q.outcome, 1, PATINDEX('%[0-9]%', q.outcome ) - 1)
ELSE q.outcome
END outcome
FROM (
select
ID,
substring (Eventlog, CHARINDEX('to - usr', EventLog) + 16, LEN(Eventlog)) AS outcome
from Summary
)q

The problem occurs because there's a newline at the end of the outcome.
So you could remove all the Carriage Returns and Line Feed characters from it
...
ID,
Replace(Replace(substring(Eventlog, CHARINDEX('to - usr', EventLog) + 16, LEN(Eventlog)),CHAR(10),''),CHAR(13),'') AS outcome
...

You have not shared the output of your query so not sure what data you are getting. Please try below sql:
SELECT ID,outcome FROM (
SELECT
ID,
CASE
WHEN PATINDEX('%[0-9]%', q.outcome) <> 0
THEN SUBSTRING(q.outcome, 1, PATINDEX('%[0-9]%', q.incoming ) - 1)
ELSE q.outcome
END outcome,
ROW_NUMBER OVER() AS SNO
FROM (
select
ID,
substring (Eventlog, CHARINDEX('to - usr', EventLog) + 16, LEN(Eventlog)) AS outcome
from Summary
)q
) A
WHERE mod(A.SNO,2) = 1

Related

create a calculated column from comparing two columns based off a substring in the columns in sql

I have the following dataset
Drawing Name
Line Number
Line Details
PL00XXX-0705-1300
2"-MSH-0513-16-C1-1 1/2"A
MATCH
PL00XXX-0705-1100
2"-MSH-0513-16-C1-2"AE
DUPLICATE / HEAT TRACE
PL00XXX-0705-1300
2"-WWS-0513-15-C1-0"
MATCH / NON ISO
PL00XXX-0705-1300
2"-WWS-0513-15-C1-2"AE
MATCH / HEAT TRACE
PL00XXX-0705-1100
2"-WWS-0513-15-C1-2"AE
DUPLICATE / HEAT TRACE
PL00XXX-0705-1300
2"-WWS-0513-17-C1-2"AE
DO NOTHING
PL00XXX-0705-1100
2"-WWS-0513-18-C1-2"AE
DO NOTHING
The new calculated column I want to create is Line Details based if there are at LEAST 2 of a line number up to the last dash in the line number. IF there is not at least 2 of the same up to the last dash - do nothing.
The Line Details column shows Match if the drawing number would have 05-13 in it and the line number would have 0513 in it.
The Line Details column would show Duplicate if the drawing number had 05-13 in it and the line number had 0511 in it.
The Line Details column could ALSO show Heat Trace if the line number ends with an E.
The Line Details column could ALSO show Non Iso if the line number ends with 0".
The drawing number up to PL00XXX-07 is always the same per customer. it's what comes after that is important and how it's tied or not tied to the line number. At least 2 of the same line number means up to the - after C1. The amount of characters prior to that could be different, there could be a 2" line or a 1/2" line, but as long as the line number matches up to the C1- part of the line that represents 2 of the same.
IF this makes send PLEASE help. Greatly appreciated.
How can a query be written to only find duplicates up to the last hypen? I have the following line numbers:
2"-MSH-0513-16-S1-**1 1/2"A
2"-MSH-0513-16-S1-**2"AE
2"-MSH-0513-17-S1-**1 1/2"A
2"-MSH-0513-18-S1-**1 1/2"A
2"-FLW-0521-18-S1-**1"A
2"-FLW-0521-18-S1-**1"A
So the line numbers that I want to be shown in the list after the query is as follows:
2"-MSH-0513-16-S1-**1 1/2"A
2"-MSH-0513-16-S1-**2"AE
2"-FLW-0521-18-S1-**1"A
2"-FLW-0521-18-S1-**1"A
I know how to query a specific character count ONLY when the data is the exact same character count in the column. As you can see the character count can be different up the the last hyphen.
I have tried the following script:
select SUBSTRING(LINE_NUM_CONCAT_,
1,
regexp_instr(LINE_NUM_CONCAT_,
'-',
1,
regexp_count(LINE_NUM_CONCAT_,
'-')
) - 1)
FROM PID_Components_PROCESS_LINES
but regex_count is not a recongnized built-in function name???
PLEASE help.
use CASE expression to evaluate your condition and return the string accordingly and concatenate all as one string
to check for duplicates use window function count(*) over (partition by ...)
select [Drawing Name], [Line Number],
[Line Details] =
case when count(*) over (partition by line) < 2
then 'DO NOTHING'
else
case when [Drawing Name] like '%05-13%'
and [Line Number] like '%0513%'
then 'MATCH'
else ''
end
+ case when [Drawing Name] like '%05-11%'
and [Line Number] like '%0513%'
then 'DUPLICATE'
else ''
end
+ case when right([Line Number], 1) = 'E'
then '/ HEAT TRACE'
when right([Line Number], 2) = '0"'
then '/ NON ISO'
else ''
end
end
from PID_Components_PROCESS_LINES p
cross apply
(
select line = left([Line Number],
len([Line Number]) - charindex('-', reverse([Line Number]))
)
) l
where p.[Drawing Name] like 'PL00528%'
I have reorganized the query and using APPLY() operator to compute the various value. You can add the WHERE condition to exclude the NO NOTHING lines.
select *,
case when line_count < 2
then 'DO NOTHING'
else
m.match
+ duplicate
+ case when right([Line Number], 1) = 'E'
then '/ HEAT TRACE'
when right([Line Number], 2) = '0"'
then '/ NON ISO'
else ''
end
end
from (
select *, line_count = count(*) over (partition by line)
from PID_Components_PROCESS_LINES
cross apply
(
select line = left([Line Number],
len([Line Number]) - charindex('-', reverse([Line Number])))
) l
where [Drawing Name] like 'PL00528%'
) p
cross apply
(
select match = case when [Drawing Name] like '%05-13%'
and [Line Number] like '%0513%'
then 'MATCH'
else ''
end
) m
cross apply
(
select duplicate = case when [Drawing Name] like '%05-11%'
and [Line Number] like '%0513%'
then 'DUPLICATE'
else ''
end
) d
where p.line_count >= 2 -- exclude the do nothing lines

Count of numbers followed by pipe symbol in a single data of a column in SQL Server

LEN(Column)-len(Replace(Column,'|','') will give total count of Pipe available in a single row data of a SQL Server.
But I need to count the number of records that has Pipe Symbol followed immediately to Number,
**Eg 1:** MNY-THY-**2|** *YUI_WER-NA|JIU-ERT-**8|***
The output of the above record is 2.
**Eg 2:** *MNY-YU-NA|*
The output is 0
**Eg 3:** *MNY-9876**5|***
The output is 1
UPDATE TO MY QUESTION BASED ON ANSWERS SUGGESTED:
**Eg 4:** MNY-YU-1234
The output is 0 Since there is no '|' symbol in my example 4, the result should be 0 only.
Any suggestion would be highly supportable.
You can Split the String based on the "|" and Check the value from the right Side whether it contains number or not.
DECLARE #tosearch VARCHAR(MAX)='%[0-9]|%' ,#string VARCHAR(MAX)='FGL_NU_0003'
SELECT COUNT(CASE WHEN RIGHT(VALUE,1) LIKE '[0-9]' THEN 1 ELSE NULL END)
FROM STRING_SPLIT(#string,'|')
WHERE #string LIKE '%|%'
Expected Output:
MNY-YU-1234 - 0
If you are using SQL Server 2016+, STRING_SPLIT() is an option:
Table:
SELECT *
INTO Data
FROM (VALUES
('MNY-THY-2| YUI_WER-NA|JIU-ERT-8|'),
('MNY-YU-NA|'),
('MNY-98765|'),
('FGL_NU_0003')
) v (TextData)
Statement:
SELECT *
FROM Data d
OUTER APPLY (
SELECT COUNT(*) AS NumberCount
FROM STRING_SPLIT(d.TextData, '|') s
WHERE (d.TextData LIKE '%|%') AND (RIGHT(s.[value], 1) LIKE '[0-9]')
) a
Result:
TextData NumberCount
MNY-THY-2| YUI_WER-NA|JIU-ERT-8| 2
MNY-YU-NA| 0
MNY-98765| 1
FGL_NU_0003 0

Query for date value AFTER specified patindex value in TEXT column using SQL Server

I am querying for a date value that follows a specific phrase in the same text column value. There are a number of date values in this text column but I'm needing only the DATE following the phrase I've found via a patindex value. Any help/direction would be appreciated. Thanks.
Here is my SQL code:
SELECT
NotesSysID,
PATINDEX('%Demand Due Date:%', NoteText) AS [Index of DemandDueDate text],
PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%', NoteText) AS [Index of DemandDueDate date],
SUBSTRING(NoteText, PATINDEX('%Demand Due Date:%', NoteText), (PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%', NoteText)))
FROM
#temp_ExtractedNotes;
Here is a pic of my data, please note that the 2nd index is LESS than the Index of DemandDueDate text found and I'm needing the subsequent date AFTER the Index of DemandDueDate text column. Hopefully this makes sense.
I think your code will be easier for you to work with if you use a CTE and some stepwise refinement. That'll free you from trying to do everything with one hugely-nested SELECT statement.
;
WITH FirstCut as (
SELECT
NotesSysID,
LocationOfText = PATINDEX('%Demand Due Date:%', NoteText),
NoteText
FROM #temp_ExtractedNotes
),
SecondCut as (
SELECT
NotesSysID,
NoteText,
-- making assumption date will be within first 250 chars of text
DemandDueDateSection = SUBSTRING( NoteText, [LocationOfText], 250)
FROM FirstCut
),
ThirdCut as (
SELECT
NotesSysID,
NoteText,
DemandDueDateSection,
LocationOfDate = PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%', DemandDueDateSection)
FROM SecondCut
),
FourthCut as (
SELECT
NotesSysID,
NoteText,
DateAsText = SUBSTRING( DemandDueDateSection, LocationOfDate, 10 )
FROM ThirdCut
)
SELECT
NotesSysID,
NoteText,
DemandDueDate = CONVERT( DateTime, DateAsText)
FROM FourthCut
The issue you're having is because your second PATINDEX isn't finding the date you want; it's finding the first date in the string, which, as you noted, appears before the PATINDEX of the phrase you're searching for %Demand Due Date:%. The third parameter of SUBSTRING is LENGTH, which is to say how many characters after the second parameter you want to pull. By using that second PATINDEX value as the third parameter in your SUBSTRING you're returning a sub-string that starts where you want it to, and is of LENGTH equal to the number of characters into the string where that first date appears.
Which, of course, isn't what you want. To #ZLK's point in the comments, first, you need to do a nested PATINDEX. That's going to be pretty slow, so I'm hoping there aren't a bazillion records in your temp table.
Based on the sample image, it looks like the date you're interested in can appear a variable number of characters after %Demand Due Date:%. We'll start by adding 16 to the PATINDEX of %Demand Due Date:% (because that's how many characters are in %Demand Due Date:%, so we'll just start right after that). Then we'll pick up the next 100 characters. You can tweak that later if you need more or not that many.
So you're first SUBSTRING will look like this:
SUBSTRING(NoteText, PATINDEX('%Demand Due Date:%', NoteText) + 16, 100)
Now we have to search that sub-string for the second pattern, the one that should yield a date for you.
PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%', SUBSTRING(NoteText, PATINDEX('%Demand Due Date:%', NoteText) + 16, 100))
The number returned there is the point where your date value starts within the 100 characters following %Demand Due Date:%. Armed with that number, you just need to SUBSTRING out the next ten characters, and, just for fun, CAST it as a DATE. That big ugly formula will look like this:
DECLARE #test VARCHAR(200) = 'foo bar Demand Due Date: 12/21/2018 bar foo foo bar';
SELECT
CAST(
SUBSTRING(
SUBSTRING
(#test, PATINDEX('%Demand Due Date:%', #test) + 16, 100),
PATINDEX
( '%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',
SUBSTRING
(#test, PATINDEX('%Demand Due Date:%', #test) + 16, 100)
)
,10)
AS DATE);
Result:
2018-12-21
Rextester: https://rextester.com/KCY79989
Grab a copy of PatternSplitCM.
CREATE FUNCTION dbo.PatternSplitCM
(
#List VARCHAR(8000) = NULL
,#Pattern VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
WITH numbers AS (
SELECT TOP(ISNULL(DATALENGTH(#List), 0))
n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n))
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
Item = SUBSTRING(#List,MIN(n),1+MAX(n)-MIN(n)),
Matched
FROM (
SELECT n, y.Matched, Grouper = n - ROW_NUMBER() OVER(ORDER BY y.Matched,n)
FROM numbers
CROSS APPLY (
SELECT Matched = CASE WHEN SUBSTRING(#List,n,1) LIKE #Pattern THEN 1 ELSE 0 END
) y
) d
GROUP BY Matched, Grouper;
Then it's pretty easy:
-- Sample Data
DECLARE #temp_ExtractedNotes TABLE (someID INT IDENTITY, NoteText VARCHAR(8000));
INSERT #temp_ExtractedNotes (NoteText) VALUES
('blah blah blah 2/4/2016... Demand Due Date: 1/05/2011; blah blah 12/1/2017...'),
('Yada yad..... Demand Due Date: 11/21/2016;...'),
('adas dasd asd a sd asdas Demand Due Date: 09/09/2019... 5/05/2005, 10/10/2010....'),
('nothing to see here - moving on... 01/02/2003!');
-- Solution
SELECT TOP (1) WITH TIES t.someID, ns.s, DueDate = CASE SIGN(nt.s) WHEN 1 THEN f.item END
FROM #temp_ExtractedNotes AS t
CROSS APPLY (VALUES(CHARINDEX('Demand Due Date:',t.NoteText))) AS nt(s)
CROSS APPLY (VALUES(SUBSTRING(t.noteText, nt.s+16, 8000))) AS ns(s)
CROSS APPLY dbo.patternsplitCM(ns.s,'[0-9/]') AS f
WHERE f.matched = 1
ORDER BY ROW_NUMBER() OVER (PARTITION BY t.someID ORDER BY f.itemNumber);
Results:
someID s DueDate
----------- ---------------------------------------- ------------
1 1/05/2011; blah blah 12/1/2017... 1/05/2011
2 11/21/2016;... 11/21/2016
3 09/09/2019... 5/05/2005, 10/10/2010.... 09/09/2019
4 here - moving on... 01/02/2003! NULL

Window function behaves differently in Subquery/CTE?

I thought the following three SQL statements are semantically the same. The database engine will expand the second and third query to the first one internally.
select ....
from T
where Id = 1
select *
from
(select .... from T) t
where Id = 1
select *
from
(select .... from T where Id = 1) t
However, I found the window function behaves differently. I have the following code.
-- Prepare test data
with t1 as
(
select *
from (values ( 2, null), ( 3, 10), ( 5, -1), ( 7, null), ( 11, null), ( 13, -12), ( 17, null), ( 19, null), ( 23, 1759) ) v ( id, col1 )
)
select *
into #t
from t1
alter table #t add primary key (id)
go
The following query returns all the rows.
select
id, col1,
cast(substring(max(cast(id as binary(4)) + cast(col1 as binary(4)))
over (order by id
rows between unbounded preceding and 1 preceding), 5, 4) as int) as lastval
from
#t
id col1 lastval
-------------------
2 NULL NULL
3 10 NULL
5 -1 10
7 NULL -1
11 NULL -1
13 -12 -1
17 NULL -12
19 NULL -12
23 1759 -12
Without CTE/subquery: then I added a condition just return the row which Id = 19.
select
id, col1,
cast(substring(max(cast(id as binary(4)) + cast(col1 as binary(4))) over (order by id rows between unbounded preceding and 1 preceding), 5, 4) as int) as lastval
from
#t
where
id = 19;
However, lastval returns null?
With CTE/subquery: now the condition is applied to the CTE:
with t as
(
select
id, col1,
cast(substring(max(cast(id as binary(4)) + cast(col1 as binary(4))) over (order by id rows between unbounded preceding and 1 preceding ), 5, 4) as int) as lastval
from
#t)
select *
from t
where id = 19;
-- Subquery
select
*
from
(select
id, col1,
cast(substring(max(cast(id as binary(4)) + cast(col1 as binary(4))) over (order by id rows between unbounded preceding and 1 preceding), 5, 4) as int) as lastval
from
#t) t
where
id = 19;
Now lastval returns -12 as expected?
The logic order of operations of the SELECT statement is import to understand the results of your first example. From the Microsoft documentation, the order is, from top to bottom:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
Note that the WHERE clause processing happens logically before the SELECT clause.
The query without the CTE is being filtered where id = 19. The order of operations causes the where to process before the window function in the select clause. There is only 1 row with an id of 19. Therefore, the where limits the rows to id = 19 before the window function can process the rows between unbounded preceding and 1 preceding. Since there are no rows for the window function, the lastval is null.
Compare this to the CTE. The outer query's filter has not yet been applied, so the CTE operates an all of the data. The rows between unbounded preceding finds the prior rows. The outer part of the query applies the filter to the intermediate results returns just the row 19 which already has the correct lastval.
You can think of the CTE as creating a temporary #Table with the CTE data in it. All of the data is logically processed into a separate table before returning data to the outer query. The CTE in your example creates a temporary work table with all of the rows that includes the lastval from the prior rows. Then, the filter in the outer query gets applied and limits the results to id 19.
(In reality, the CTE can shortcut and skip generating data, if it can do so to improve performance without affecting the results. Itzik Ben-Gan has a great example of a CTE that skips processing when it has returned enough data to satisfy the query.)
Consider what happens if you put the filter in the CTE. This should behave exactly like the first example query that you provided. There is only 1 row with an id = 19, so the window function does not find any preceding rows:
with t as ( select id, col1,
cast(substring(max(cast(id as binary(4)) + cast(col1 as binary(4))) over ( order by id
rows between unbounded preceding and 1 preceding ), 5, 4) as int) as lastval
from #t
where id = 19 -- moved filter inside CTE
)
select *
from t
Window functions operate on your result set, so when you added where id = 19 your result set only had 1 row. Since your window function specifies rows between unbounded preceding and 1 preceding there was no preceding row, and resulted in null.
By using the subquery/cte you are allowing the window function to operate over the unfiltered result set (where the preceding rows exist), then retrieving only those rows from that result set where id = 19.
The querys you are comparing are not equivalent.
select id ,
(... ) as lastval
from #t
where id = 19;
will take only 1 row, so 'lastval' will take NULL from col1 as for the windowed function does not find preceding row.

Get COUNT() of rows where first 3 digits of column are alike

I have a result set of codes that are usually three digits followed by up to 2 digits like 012.34 or 123.45. The first three digits define a general category of group, and the digits following the decimal place define more specific qualities. There could be 77 012.xx numbers, and there are hundreds of unique 3 digit group definitions, followed by a varying number of digits per entry.
Does anyone know how to write a quick query to achieve this?
Assuming it is in a varchar column since you're storing 012.34...
SELECT LEFT(someColumn,3), COUNT(*)
FROM someTable
GROUP BY LEFT(someColumn,3)
HAVING COUNT(*) > 5 -- per your comments
ORDER BY LEFT(someColumn,3)
If it's not, then you'd do this:
SELECT LEFT(CONVERT(VARCHAR(10),someColumn),3), COUNT(*)
FROM someTable
GROUP BY LEFT(CONVERT(VARCHAR(10),someColumn),3)
ORDER BY LEFT(CONVERT(VARCHAR(10),someColumn),3)
#rypress these look strikingly similar to ICD-9 Diagnosis codes for Other respiratory tuberculosis ClickMe. Is this correct? In that case you will get Category and subcategory in your result and may change your counts(012->012.0->012.00,012.02..)
Sample Data:
IF OBJECT_ID(N'TempICD') > 0
BEGIN
DROP TABLE TempICD
END
CREATE TABLE TempICD (ICD VARCHAR(10))
INSERT INTO TempICD
VALUES ('012'),('012.0'),('012.00'),('012.01'),('012.02'),
('012.03'),('012.04'),('012.05'),('012.05'),
('013'),('013.0'),('013.00'),('013.01'),('013.02'),
('013.03'),(NULL)
Query to get Category with 6 or more line items (Including Category and Sub Category):
SELECT LEFT(ICD, 3) AS ICDs,
COUNT(1) AS ICDCount
FROM TempICD
GROUP BY LEFT(ICD, 3)
HAVING COUNT(*) > 5
ORDER BY LEFT(ICD, 3)
Query to get Category with 6 or more line items (Excluding Category and Sub Category):
SELECT SUBSTRING(ICD, 1, CHARINDEX('.', ICD + '.') - 1) AS ICDs,
SUM(CASE
WHEN LEN(SUBSTRING(ICD, CHARINDEX('.', ICD) + 1, LEN(ICD))) = 2 THEN 1
ELSE 0
END) AS ICDCount
FROM TempICD
WHERE ICD IS NOT NULL
GROUP BY SUBSTRING(ICD, 1, CHARINDEX('.', ICD + '.') - 1)
HAVING SUM(CASE
WHEN LEN(SUBSTRING(ICD, CHARINDEX('.', ICD) + 1, LEN(ICD))) = 2 THEN 1
ELSE 0
END) > 5
Cleanup Script:
IF OBJECT_ID(N'TempICD') > 0
BEGIN
DROP TABLE TempICD
END
This may also help you.
I assume that the column is Decimal Data type.
SELECT CAST([COLUMN] AS INT) [GROUP],
COUNT(*) [COUNT]
FROM [TABLE] T
GROUP BY CAST([COLUMN] AS INT)
it depends if your resultset is numeric or characters. if not numeric you can use string operations.
select left(resultSet,charindex('.',resultset)) , count(*)
from x
group by by left(resultSet,charindex('.',resultset))
order by left(resultSet,charindex('.',resultset))
with charindex you will get a correct 'cut' when the first digits are not 3 as 'usually'.
if your resultset is numeric/float you can use the floor function
select floor(resultset),count(*)
from x
group by floor(resultset)
order by floor(resultset)

Resources