Split snowflake db columns based on a delimiter - snowflake-cloud-data-platform

got a bit stuck with SPLIT condition and looking for a hand with how to get the result
got a string:
03::AccountID:23.04.2019;;AccountNum:1234567;;ActiveDate:Jan 1 1900 12:00AM;;BankAccount:12;11;
The formatting condition is ColumnName:NewValue;OldValue;
result wanted is:
COLUMN_N
OLD_VALU
NEW_VALUE
AccountID
23.04.2019
AccountNum
1234567
ActiveDate
Jan 1 1900 12:00AM
BankAccount
12
11
Thanks all for help!
So far I've tried multiple CTE's with latteral split based on different delimiter but found it difficult to get around where the new column name begins

Its not as easy as it looks - it need multiple level of splits.
replaced :: by ;; so that all columns have same delimitter.
Then splitted them based on ;;
split last column based on ;
select split(table1.value,':')[0] COLUMN_N,split(split(table1.value,':')[1],';')[0] old
,split(split(table1.value,':')[1],';')[1] new
from table(split_to_table( replace('03::AccountID:23.04.2019;;AccountNum:1234567;;ActiveDate:Jan 1 1900 12:00AM;;BankAccount:12;11;','::',';;'), ';;')) as table1
order by table1.value

Related

How to configure a table column in TSQL that works as a sequence depending on the values of another two columns?

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.

SQL Server - conditionally delete part of a string within a field

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

SQL Server Get row value when using MAX

I have a table which holds a date field and an integer field like the example below:
Date Number
01/01/2017 9
02/01/2017 13
03/01/2017 16
04/01/2017 2
15/01/2017 4
20/01/2017 8
27/01/2017 1
I want to write a query selecting the MAX(date) where the date is <= 13/01/2017 (which would give me 04/01/2017) and return the number column value associated with it (2 in this example).. I can of course write 2 queries getting one and using the result to find the next but I hope there is another way using only one statement. It probably would help if I knew how to word this so I haven't had much luck searching for a solution..
Thank you in advance..
Derek
Use TOP 1 and Order By
select Top 1 * from yourtable where [date] <= CONVERT(DATE, '13/01/2017', 103)
order by date desc
Better to use yyyy-mm-dd format for your date input

Appending data in SQL Server

Question: I have a table that has a column called DOB. In it is well... dates of birth, but in a format such as 04/22/1987. I'd like to change them to 19870422, which would entail moving the 4 digit year to the front of the cell and deleting the / marks and leaving no spaces.
Any suggestions in an efficient was to do this would be much appreciated. thanks everyone!
If your table is called Foo and your column name is DOB:
Update Foo
Set DOB = Substring(DOB, 7, 4) + Substring(DOB, 1, 2) + Substring(DOB, 4, 2);
Here's a SQL Fiddle.
Note that this will update the DOB column for all rows in your table. So, be certain that all of your data is in the format MM/DD/YYYY before changing it to YYYYMMDD.
Note that the Substring() function takes three parameters:
Input (often text, but could be binary)
Starting point (which is one-based)
Total number of characters to return.
So, the expression Substring(DOB, 7, 4) starts at the seventh position (the beginning of the year) and takes four characters (the four-character year.)
Select Convert(char(8),dob,112) dob
So you want to update all rows within the date column basically updating the existing columns
UPDATE YourTable SET YourNewColumn = CONVERT(DATETIME,YourOldColumn,112)

MSSQL Comparing rows same table

Hi im looking to compare several rows and check if a certain condition is true/false.
The tables has several columns the ones im interested in are:
Events.Badgeno
Events.Name
Events.Date
Events.Time
Events.Region_id
Events.Data
The region ID can either be 1 or 2.
I want to check weather the same badgeno registers with a different region within a specified date/time difference say 10 mins. (Could be 10 mins before or 10 mins after).
I'm looking to show the records which don't have a record against the 2 regions.
As a further note it should only be within the first and last records of that badge per day.
Normally each record should have a region 1 and 2 record at the start and end. But there maybe multiple region 1's through out the day.
Any suggestions for the best method?
Id Date Time Name Badgeid Region
3385033 27/02/2014 08:16:11 FirstName Surname 5304 2
I think something like this would work
SELECT e.Badgeno,e.Name, e.Date, e.Time,e.Region_id, e.Data
FROM events e
INNER JOIN events e1 ON e1.BadgeNo = e.BadgeNo AND e1.Region_id <> e.RegionId AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) > -10 AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) < 10
WHERE e1.Region_id IS NULL
you should provide sample data.
This Query is not complete,you can try something with
row_number/rank/dense, partition and check thus number column
generated .
select *,
row_number()over(partition by badgeno,regionno order by badge no)rn from table
where condition of date time

Resources