I have a string like this [Enity:Equipment]#[Property:Space]
And i want 2 matches.
1: match Equipment
2 match Space
i cant figure out.
I have tried this
\[(.*?)\]
As you tagged the question with the "database" tag, and as Oracle is one of databases, see whether such a regexp_substr helps; basically, it returns 2nd and 4th word from the input string, presuming that format is exactly as you put it.
SQL> with test(col) as
2 (select '[Enity:Equipment]#[Property:Space]' from dual)
3 select regexp_substr(col, '\w+', 1, 2) as equipment,
4 regexp_substr(col, '\w+', 1, 4) as space
5 from test;
EQUIPMENT SPACE
--------- -----
Equipment Space
SQL>
Related
I have a table that looks like this:
ID A B Count
-----------------
1 abc 0 1
2 abc 0 2
3 abc 1 1
4 xyz 1 1
5 xyz 1 2
6 xyz 1 3
7 abc 1 2
8 abc 0 3
The "Count" column is incremented by one in the next insertion depending on the value of fields "A" and "B". so for example, if the next record I want to insert is:
ID A B Count
-----------------
abc 0
The value of count will be 4.
I have been trying to find documentation about this, but I'm still quite lost in the MS SQL world! There must be a way to configure the "Count" column as a sequence dependent on the other two columns. My alternative would be to select all the records with A=abc and B=0, get the maximum "Count", and do +1 in the latest one, but I suspect there must be another way related to properly defining the Count column when creating the table.
The first question is: Why do you need this?
There is ROW_NUMBER() which will - provided the correct PARTITION BY in the OVER() clause - do this for you:
DECLARE #tbl TABLE(ID INT,A VARCHAR(10),B INT);
INSERT INTO #tbl VALUES
(1,'abc',0)
,(2,'abc',0)
,(3,'abc',1)
,(4,'xyz',1)
,(5,'xyz',1)
,(6,'xyz',1)
,(7,'abc',1)
,(8,'abc',0);
SELECT *
,ROW_NUMBER() OVER(PARTITION BY A,B ORDER BY ID)
FROM #tbl
ORDER BY ID;
The problem is: What happens if a row is changed or deleted?
If you write this values into a persistant column and one row is removed physically, you'll have a gap. Okay, one can live with this... But if a value in A is changed from abc to xyz (same applies to B of course) the whole approach breaks.
If you still want to write this into a column you can use the ROW_NUMBER() from above to fill these values initially and a TRIGGER to set the next value with your SELECT MAX()+1 approach for new rows.
If the set of combinations is limited you might create a SEQUENCE (needs v2012+) for each.
But - to be honest - the whole issue smells a bit.
I checked both of these:
Delete part of a field in SQL
Deleting part of a string in MYSQL
but they're not quite what I need.
I've unfortunately inherited a table with a field full of comma-separated strings with no regard for format or order. It's ugly. Now I need to get rid of a particular part of a string:
So let's say I have a table as such:
Column1 Column2
1 XRR01,MMEX1,XFR44
2 XRR02,MMEX1
3 MMEX1,GH345,XFR45,CFA34
4 NMM22,MMEX1,XFR44
5 MMEX1
6 XFR55
I want to do an UPDATE to find and delete any instances of MMEX1 from the Column2 field, and keep the other parts intact.
So then I would be left with:
Column1 Column2
1 XRR01,XFR44
2 XRR02
3 GH345,XFR45,CFA34
4 NMM22,XFR44
5 NULL (or blank, doesn't really matter)
6 XFR55
Is this possible?
Here is one way using Replace function
select replace(replace(Column2,',MMEX1',''),'MMEX1,','')
from Yourtable
replace(Column2,',MMEX1','') will remove the string in middle and last
replace(Column2,'MMEX1,','') will remove the string at the start
Note : storing comma sepearated value in a column is always a pain when comes to data processing. Try and change the table structure
As part of our OLAP modeling workflow, we are often truncating fields as upstream data sources have no restrictions or defined data types. A field which should be a 10 character string can sometimes be 50 or 100 characters long if it is a free form user input. I've been told this can cause problems with downstream processes which involve uploads to external sources.
I've been asked to find a way to identify instances in which one ore more of these fields is truncated.
How we handle these fields now is something like this:
SELECT
LEFT(FreeResponseField, 10) AS Comment
INTO
dbo.ModeledTable
FROM
dbo.SourceTable
Essentially if the field is greater than 10 characters, who cares, we only take the first 10.
If dbo.SourceTable.FreeResponseField has a length greater than 10, now we want to know somehow (be it a warning/error message or insertion into a log table). We have a lot of tables with a lot of fields, so the above example is a simplification. Identifying just the field in which this occurs and/or the tuple in the table would be helpful to see where these issues are occurring.
Is something like this possible? You can't just compare data types of the source table with the target table as the source table sets everything to essentially VARCHAR(MAX). The naive approach is to check the length every single value of every tuple against the defined length of the target table.
The original specifications weren't descriptive, but I've figured out a solution and thought I'd share in case anyone stumbles across this for some reason.
Imagine we have a SourceTable which are pulling in to our model. We have defined zip codes as being of length 5 and addresses of being length 25. Say we have the following two records:
CustomerID | ZipCode | Address
1 | 90210 | 123 Fake Street
2 | 902106 | 546 Fake Street
Based on our model definitions, there is an error with ZipCode for the record where CustomerID equals 2. We would like to identify both ZipCode as being the problem field and the record where CustomerID equals 2. The following query with a CROSS APPLY does that:
WITH CTE AS (
SELECT
CustomerID,
ZipCodeFlag = IIF(LEN(ZipCode) > 5, 1, 0),
AddressFlag = IIF(Len(Address) > 25, 1, 0),
ZipCode,
Address
FROM
SourceTable
)
SELECT
CustomerID,
TruncatedField,
RawValue
FROM
CTE
CROSS APPLY (
VALUES ('ZipCode', ZipCodeFlag, ZipCode),
('Address', AddressFlag, Address)
) CA(TruncatedField, TruncatedFlag, RawValue)
WHERE
TruncatedFlag = 1
ORDER BY
CustomerID
With the following output:
CustomerID | TruncatedField | RawValue
2 | ZipCode | 902106
I currently have this table (myTable) in my database:
user start
----------------------------
Adam 12345
Alex 123
Benny 2345
In my program, I accept a string from user, eg: 12345678
My objective is to select out the row where user input starts with myTable.Start
-- For example, it would be great to have something like:
select * from myTable where "12345678".startsWith(start)
-- and returns me Adam, 12345 & Alex, 123
As of now I'm using
select user, start
from myTable where charindex(start, "12345678") = 1
order by start desc
which does the job, but in absolute terrible performance, myTable row count is about near a million, I'm not sure if indexing start would help as I'm not doing a direct compare in this case.
Does anyone know a better way to accomplish this?
Try this,
select user, start
from myTable
where '12345678' like start+'%'
order by start desc
Also add an index to the column start.
You should use the pattern matching operator, LIKE operator AND add an index to the column, eg:
select user, start
from myTable where start LIKE "12345678%"
order by start desc
Without the index performance will be as bad as before - the server would have to check all rows for matches.
With an index, the operation becomes a range search: rows where start is greater or equal to 12345678 but less than the next higher string lexically (12345679). Range searches can use indexes and load process only the matching lines
EDIT
Oops, missed that the query tries to do the opposite - find rows that can act as prefixes to a string. This can't be accelerated with indexes because it's equivalent to
"someconstantvalue" LIKE start +'%'
This has to generate a new value for each row before matching, so can't use any indexes
Is there any way to order the result (for example)
SELECT id,age, Location
FROM Student
WHERE Location in ('NY','DC','MI','TE')
instead of having them as
id age Location
1 2 DC
2 2 NY
4 2 MI
6 2 TE
The Result should be ordered as the order of in ('NY','DC','MI','TE'):
id age Location
2 2 NY
1 2 DC
4 2 MI
6 2 TE
I figured that It's possible by having a temp table and inserting the ('NY','DC','MI','TE') into this table. Then using a left join will order it as wanted.
Is there a better solution.
Please Advise.
In MySQL this can be done using FIND_IN_SET, which gives back the index of the occurrence of the first argument in the second, the latter being a string containing comma-separated values.
I think the same thing should be possible using CHARINDEX - give this a try:
SELECT id, age, location
FROM student
WHERE location IN ('NY','DC','MI','TE')
ORDER BY CHARINDEX (location, 'NY,DC,MI,TE')
Any solution would be roughly the equivalent of using a temp table. You could use a CTE or a subquery, but you are essentially using different syntax to perform the same operation.
Assuming you don't have to select city codes from a table, try some of the following:
ORDER BY FIELD(Location,'NY','DC','MI','TE')
ORDER BY FIND_IN_SET(Location,'NY,DC,MI,TE')
ORDER BY LOCATE(CONCAT(',',Location,','),',NY,DC,MI,TE,')
ORDER BY Location IN ('NY','DC','MI','TE')
IN could also accept a sub-query (ORDER BY Location IN SELECT city_code FROM ...)