How to remove extension dates in SQL server?
FileName | id
-------------------------+---
c:\abc_20181008.txt | 1
c:\xyz_20181007.dat | 2
c:\abc_xyz_20181007.dat | 3
c:\ab.xyz_20181007.txt | 4
Based on above data I want output like below :
Table: emp
FileName | id
-------------------+---
c:\abc.txt | 1
c:\xyz.dat | 2
c:\abc_xyz.dat | 3
c:\ab.xyz.txt | 4
I have tried like this:
select
substring (Filename, replace(filename, '.', ''), len(filename)), id
from
emp
But this query is not returning the expected result in SQL Server.
Please tell me how to write a query to achieve this task in SQL Server.
You can use the following query:
SELECT id, filename,
LEFT(filename, LEN(filename) - i1) + RIGHT(filename, i2 - 1)
FROM emp
CROSS APPLY
(
SELECT CHARINDEX('_', REVERSE(filename)) AS i1,
PATINDEX('%[0-9]%', REVERSE(filename)) AS i2
) AS x
Demo here
You can try this as well:
declare #t table (a varchar(50))
insert into #t values ('c:\abc_20181008.txt')
insert into #t values ('c:\abc_xyz_20181007.dat')
insert into #t values ('c:\ab.xyz_20181007.txt')
insert into #t values ('c:\ab.xyz_20182007.txt')
select replace(SUBSTRING(a,1,CHARINDEX('2',a) - 1) + SUBSTRING(a,len(a)-3,LEN(a)),'_.','.') from #t
Related
I have a Table Animals
Id | Name | Count | -- (other columns not relevant)
1 | horse | 11
2 | giraffe | 20
I want to try to insert or update values from a CSV string
Is it possible to do something like the following in 1 query?
;with results as
(
select * from
(
values ('horse'), ('giraffe'), ('lion')
)
animal_csv(aName)
left join animals on
animals.[Name] = animal_csv.aName
)
update results
set
[Count] = 1 + animals.[Count]
-- various other columns are set here
where Id is not null
--else
--insert into results ([Name], [Count]) values (results.aName, 1)
-- (essentially Where id is null)
It looks like what you're looking for is a table variable or temporary table rather than a common table expression.
If I understand your problem correctly, you are building a result set based on data you're getting from a CSV, merging it by incrementing values, and then returning that result set.
As I read your code, it looks as if your results would look like this:
aName | Id | Name | Count
horse | 1 | horse | 12
giraffe | 2 | giraffe | 21
lion | | |
I think what you're looking for in your final result set is this:
Name | Count
horse | 12
giraffe | 21
lion | 1
First, you can get from your csv and table to a resultset in a single CTE statement:
;WITH animal_csv AS (SELECT * FROM (VALUES('horse'),('giraffe'), ('lion')) a(aName))
SELECT ISNULL(Name, aName) Name
, CASE WHEN [Count] IS NULL THEN 1 ELSE 1 + [Count] END [Count]
FROM animal_csv
LEFT JOIN animals
ON Name = animal_csv.aName
Or, if you want to build your resultset using a table variable:
DECLARE #Results TABLE
(
Name VARCHAR(30)
, Count INT
)
;WITH animal_csv AS (SELECT * FROM (VALUES('horse'),('giraffe'), ('lion')) a(aName))
INSERT #Results
SELECT ISNULL(Name, aName) Name
, CASE WHEN [Count] IS NULL THEN 1 ELSE 1 + [Count] END [Count]
FROM animal_csv
LEFT JOIN animals
ON Name = animal_csv.aName
SELECT * FROM #results
Or, if you just want to use a temporary table, you can build it like this (temp tables are deleted when the connection is released/closed or when they're explicitly dropped):
;WITH animal_csv AS (SELECT * FROM (VALUES('horse'),('giraffe'), ('lion')) a(aName))
SELECT ISNULL(Name, aName) Name
, CASE WHEN [Count] IS NULL THEN 1 ELSE 1 + [Count] END [Count]
INTO #results
FROM animal_csv
LEFT JOIN animals
ON Name = animal_csv.aName
SELECT * FROM #results
I have a table with the following schema
a | b | c
qqq | www | ddd/ff
fff | ggg | xx/zz
jjj | gwq | as/we
How would I write a query so my data comes as
a | b | c_1 | c_2
qqq | www | ddd | ff
declare #t table(a varchar(20),b varchar(20),c varchar(20))
insert into #t values('qqq','www','ddd/ff')
SELECT a, b,
left(c,charindex('/',c)-1) As c_1,
right(c,charindex('/',reverse(c))-1) As c_2
FROM #t
or, if column c does not always have the format xxx/yyy, you need to validate charindex position:
declare #t table(a varchar(20),b varchar(20),c varchar(20))
insert into #t values('qqq','www','ddd/ff'), ('qqq','www','dddff')
SELECT a, b,
case when charindex('/',c) > 0 then left(c,charindex('/',c)-1) else c end As c_1,
case when charindex('/',c) > 0 then right(c,charindex('/',reverse(c))-1) else null end As c_2
FROM #t
You can use as follows :
select LEFT(name, CHARINDEX('/', name)-1) from test_table;
where it returns the left part of the string name, before slash, and the following command returns the right part, after slash.
select RIGHT(name, CHARINDEX('/', name)-1) from test_table;
I did a whole example as you can see:
create table test_table ( name varchar(50), substr1 varchar(50), substr2 varchar(50));
insert into test_table(name) values ('sub1/sub2');
update test_table set substr1 =
(select LEFT(name, CHARINDEX('/', name)-1) from test_table);
update test_table set substr2 =
(select RIGHT(name, CHARINDEX('/', name)-1) from test_table);
select * from test_table;
The result is :
name | substr1 | substr2
sub1/sub2 | sub1 | sub2
Patindex can also be used instead of Charindex
SELECT a,b,LEFT(c,PATINDEX('%/%',c)-1), RIGHT(c,PATINDEX('%/%',REVERSE(c))-1) FROM #t
I have a table in which I copy the data based on an condition and I insert it into the same table with a different ID.As follows:
SET IDENTITY_INSERT Table ON
INSERT INTO Table (ID,GroupID,Name,link,etc..)
SELECT
(SELECT MAX(ID) FROM Table) + ROW_NUMBER()OVER (ORDER BY ID),
10500,
Name,
link
FROM Table
WHERE GroupID =10400
SET IDENTITY_INSERT Table OFF
this gives me the following table
**ID | GroupID | Link**
3 | 10400 |/testsDatas/10400/Uploads
4 | 10500 |/testsDatas/10400/Uploads //this is a new entry that the above query will enter.
The question I have is when the above query copies a row how can I change /testsDatas/10400/ to /testsDatas/10500/?
so that it looks like the following
**ID | GroupID | Link**
3 | 10400 |/testsDatas/10400/Uploads
4 | 10500 |/testsDatas/10500/Uploads //desired output
there is mulitple rows of data,with more columns that I did not add.How do I achieve this?
Would using REPLACE work for you? A simple example:]
DECLARE #table TABLE ( ID INT, name VARCHAR(50), link VARCHAR(50) )
INSERT INTO #table
VALUES
( 3, '10400', '/testsDatas/10400/Uploads' )
INSERT INTO #table
SELECT
(
SELECT MAX(ID)
FROM #table
) + ROW_NUMBER() OVER (ORDER BY ID),
10500,
REPLACE( link, name, 10500 )
FROM #table
SELECT *
FROM #table
My results:
I have an old classic ASP application which needs to insert many thousand rows into a SQL Server 2008 table. Currently the application is sending an INSERT command for each row separately, which takes a long time and meanwhile locks the table.
Is there a better way to do this? For example maybe:
Insert all rows into a temp table
and then do
SELECT INTO from the temp table
?
If you're generating the list of dates in the application itself, then you could probably generate them with the necessary additions to make this work.
In SQL Server 2008, you can insert multiple rows in a single command, which is a bit better than inserting row-by-row.
Here are a couple of examples of how you could do it, using a table variable for dummy data, and using GETDATE() to generate a few different dates (which you would obviously be generating in your application):
DECLARE #TABLE AS TABLE
(
RowID INT IDENTITY
,MyDate DATETIME
)
;
INSERT INTO #TABLE (MyDate)
VALUES
(GETDATE())
,(GETDATE()+1)
,(GETDATE()+2)
,(GETDATE()+3)
,(GETDATE()+4)
,(GETDATE()+5)
,(GETDATE()+6)
SELECT * FROM #TABLE
;
Returns:
RowID | MyDate
1 | 26/11/2017 10:51:49
2 | 27/11/2017 10:51:49
3 | 28/11/2017 10:51:49
4 | 29/11/2017 10:51:49
5 | 30/11/2017 10:51:49
6 | 01/12/2017 10:51:49
7 | 02/12/2017 10:51:49
You can also use this format:
INSERT INTO #TABLE (MyDate)
SELECT GETDATE()
UNION ALL
SELECT GETDATE() + 1
UNION ALL
SELECT GETDATE() + 2
UNION ALL
SELECT GETDATE() + 3
UNION ALL
SELECT GETDATE() + 4
UNION ALL
SELECT GETDATE() + 5
UNION ALL
SELECT GETDATE() + 6
;
SELECT * FROM #TABLE
;
Returns:
RowID | MyDate
1 | 26/11/2017 10:51:49
2 | 27/11/2017 10:51:49
3 | 28/11/2017 10:51:49
4 | 29/11/2017 10:51:49
5 | 30/11/2017 10:51:49
6 | 01/12/2017 10:51:49
7 | 02/12/2017 10:51:49
Not an ASP expert, but if you're concatenating the string in your application, you should be able to concatenate the string continuously rather than recreating it as a whole new INSERT statement for each date.
In a SQL Server table, I have a XML column where status are happened (first is oldest, last current status).
I have to write a stored procedure that returns the statuses: newest first, oldest last.
This is what I wrote:
ALTER PROCEDURE [dbo].[GetDeliveryStatus]
#invoiceID nvarchar(255)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #xml xml
SET #xml = (SELECT statusXML
FROM Purchase
WHERE invoiceID = #invoiceID )
SELECT
t.n.value('text()[1]', 'nvarchar(50)') as DeliveryStatus
FROM
#xml.nodes('/statuses/status') as t(n)
ORDER BY
DeliveryStatus DESC
END
Example of value in the statusXML column:
<statuses>
<status>A</status>
<status>B</status>
<status>A</status>
<status>B</status>
<status>C</status>
</statuses>
I want the procedure to return:
C
B
A
B
A
with ORDER BY .... DESC it return ALPHABETIC reversed (C B B A A)
How should I correct my procedure ?
Create a sequence for the nodes based on the existing order then reverse it.
WITH [x] AS (
SELECT
t.n.value('text()[1]', 'nvarchar(50)') as DeliveryStatus
,ROW_NUMBER() OVER (ORDER BY t.n.value('..', 'NVARCHAR(100)')) AS [Order]
FROM
#xml.nodes('/statuses/status') as t(n)
)
SELECT
DeliveryStatus
FROM [x]
ORDER BY [x].[Order] DESC
... results ...
DeliveryStatus
C
B
A
B
A
There is no need to declare a variable first. You can (and you should!) read the needed values from your table column directly. Best was an inline table valued function (rather than a SP just to read something...)
Better performance
inlineable
You can query many InvoiceIDs at once
set-based
Try this (I drop the mock-table at the end - carefull with real data!):
CREATE TABLE Purchase(ID INT IDENTITY,statusXML XML, InvocieID INT, OtherValues VARCHAR(100));
INSERT INTO Purchase VALUES('<statuses>
<status>A</status>
<status>B</status>
<status>A</status>
<status>B</status>
<status>C</status>
</statuses>',100,'Other values of your row');
GO
WITH NumberedStatus AS
(
SELECT ID
,InvocieID
, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr
,stat.value('.','nvarchar(max)') AS [Status]
,OtherValues
FROM Purchase
CROSS APPLY statusXML.nodes('/statuses/status') AS A(stat)
WHERE InvocieID=100
)
SELECT *
FROM NumberedStatus
ORDER BY Nr DESC
GO
--Clean-Up
--DROP TABLE Purchase;
The result
+---+-----+---+---+--------------------------+
| 1 | 100 | 5 | C | Other values of your row |
+---+-----+---+---+--------------------------+
| 1 | 100 | 4 | B | Other values of your row |
+---+-----+---+---+--------------------------+
| 1 | 100 | 3 | A | Other values of your row |
+---+-----+---+---+--------------------------+
| 1 | 100 | 2 | B | Other values of your row |
+---+-----+---+---+--------------------------+
| 1 | 100 | 1 | A | Other values of your row |
+---+-----+---+---+--------------------------+