How to derive column value based on occurrence of a phrase in Snowflake - snowflake-cloud-data-platform

I have input table as below
I want to have a derived column with the logic like
If for single value of COL1, if field COL2 has 'ABC' then DERIVED_COL will be filled with 'ABC_FIXED', if for a single value of COL2, if field COL# does not have 'ABC', then DERIVED_COL will be filled with 'ABC_NONFIXED'.
Is this possible in Snowflake?

Just do a self-join with a subset of same table with col2='ABC'. If join produces result means ABC fixed else ABC not fixed.
select orig.col1,orig.col2,
case when abc.col2 is not null then 'ABC_FIXED' else 'ABC_NOTFIXED' end derived_col
from mytable orig
left join (select distinct col1, col2 from mytable where col2='ABC') abc
on abc.col1=orig.col1

Using windowed function:
SELECT *, CASE WHEN COUNT_IF(COL2 = 'ABC') OVER(PARTITION BY COL1) > 0
THEN 'ABC_FIXED' ELSE 'ABC_NOTFIXED'
END AS DERIVED_COL
FROM tab;

Related

Compare row with other rows in the same table in sql server

I have the below records in my table,
If the HoleNumber combination is not having 'A' and 'B' for the particular datetime, we need to remove the alphabets from the number.
i.e., Remove 'A' from third record and sixth record. Because, it doesn't have B combinations for that datetime.
delete from myTable
where id in
(
select id from myTable t1
inner join
(
select [date], left([holeNumber], len(holeNumber)-1) as hNumber
from myTable
group by [date], left([holeNumber], len(holeNumber)-1)
having count(holeNumber) = 1
) tmp
on t1.[date] = tmp.[date] and left(t1.holeNumber, len(holeNumber)-1) = tmp.hNumber);
would do it, provided your requirements are strictly to remove having only 1 type of holeNumber.
DBFiddle demo

How to check for a specific condition by looping through every record in SQL Server?

I do have following table
ID Name
1 Jagan Mohan Reddy868
2 Jagan Mohan Reddy869
3 Jagan Mohan Reddy
Name column size is VARCHAR(55).
Now for some other task we need to take only 10 varchar length i.e. VARCHAR(10).
My requirement is to check that after taking the only 10 bits length of Name column value for eg if i take Name value of ID 1 i.e. Jagan Mohan Reddy868 by SUBSTRING(Name, 0,11) if it equals with another row value. here in this case the final value of SUBSTRING(Jagan Mohan Reddy868, 0,11) is equal to Name value of ID 3 row whose Name is 'Jagan Mohan Reddy'. I need to make a list of those kind rows. Can somebody help me out on how can i achieve in SQL Server.
My main check is that the truncated values of my Name column should not match with any non truncated values of Name column. If so i need to get those records.
Assuming I understand the question, I think you are looking for something like this:
Create and populate sample data (Please save us this step in your future questions)
DECLARE #T as TABLE
(
Id int identity(1,1),
Name varchar(15)
)
INSERT INTO #T VALUES
('Hi, I am Zohar.'),
('Hi, I am Peled.'),
('Hi, I am Z'),
('I''m Zohar peled')
Use a cte with a self inner join to get the list of ids that match the first 10 chars:
;WITH cte as
(
SELECT T2.Id As Id1, T1.Id As Id2
FROM #T T1
INNER JOIN #T T2 ON LEFT(T1.Name, 10) = t2.Name AND T1.Id <> T2.Id
)
Select the records from the original table, inner joined with a union of the Id1 and Id2 from the cte:
SELECT T.Id, Name
FROM #T T
INNER JOIN
(
SELECT Id1 As Id
FROM CTE
UNION
SELECT Id2
FROM CTE
) U ON T.Id = U.Id
Results:
Id Name
----------- ---------------
1 Hi, I am Zohar.
3 Hi, I am Z
Try this
SELECT Id,Name
FROM(
SELECT *,ROW_NUMBER() OVER(PARTITION BY Name, LEFT(Name,11) ORDER BY ID) RN
FROM Tbale1 T
) Tmp
WHERE Tmp.RN = 1
loop over your column for all the values and put your substring() function inside this loop and I think in Sql index of string starts from 1 instead of 0. If you pass your string to charindex() like this
CHARINDEX('Y', 'Your String')
thus you will come to know whether it is starting from 0 or 1
and you can save your substring value as value of other column with length 10
I hope it will help you..
I think this should cover all the cases you are looking for.
-- Create Table
DECLARE #T as TABLE
(
Id int identity(1,1),
Name varchar(55)
)
-- Create Data
INSERT INTO #T VALUES
('Jagan Mohan Reddy868'),
('Jagan Mohan Reddy869'),
('Jagan Mohan Reddy'),
('Mohan Reddy'),
('Mohan Reddy123551'),
('Mohan R')
-- Get Matching Items
select *, SUBSTRING(name, 0, 11) as ShorterName
from #T
where SUBSTRING(name, 0, 11) in
(
-- get all shortnames with a count > 1
select SUBSTRING(name, 0, 11) as ShortName
from #T
group by SUBSTRING(name, 0, 11)
having COUNT(*) > 1
)
order by Name, LEN(Name)

Compare 2 result sets

I am working in SQL Server 2008. I have 2 queries. The first one is:
SELECT
col1,
col2
FROM tableA
A typical result set of this query is:
col1 col2
facilityA 10
facilityB 20
The second one is:
SELECT
colx,
COUNT(*) AS 'Totals'
FROM tableB
GROUP BY colx
A typical result set of this query is:
colx Totals
facilityA 10
facilityB 50
I want to return all records in the first result set where the values are different between col2 and Totals from the second result set, for corresponding values between col1 and colx. For instance, the given example should return:
col1 col2
facilityB 20
How do I achieve this?
Sounds like you want to use the EXCEPT clause. This will compare each row column by column and if an identical row exists between the two datasets it will be excluded:
SELECT col1, col2
FROM tableA
EXCEPT
SELECT colx, COUNT(*) AS 'Totals'
FROM tableB
GROUP BY colx

Select data from one table where a field is greater than that of another field in another table

I want to be able to select data from TableA where Field1 is greater than Field2 in TableB.
In my head i image it to be something like this
Select TableA.*
from TableA
Join TableB
On TableA.PK = TableB.FK
WHERE TableA.Field1 > TableB.Field2
I am using SQL server 2005 and the TableA.Field1 and tableB.Field2 look like:
2004102881010 - data type - Vrachar
My PK and FK look like:
0908232 - data type - nvarchar
The probelm is when this query is ran ALL the data is displaying and not just the rows where Field1 is greater.
Cheers:)
Seems to be working correctly for this demo code. Perhaps I'm not understanding the problem or data.
;
with TABLEA (PK, Field1) AS
(
-- Sample row that is filtered out
SELECT CAST('0908232' AS nvarchar(10)), CAST('2004102881010' AS varchar(50))
-- This is bigger than what's in B
UNION ALL SELECT CAST('0908232' AS nvarchar(10)), CAST('2005102881010' AS varchar(50))
)
, TABLEB(FK, Field2) AS
(
-- This matches row 1 above and will be excluded
SELECT CAST('0908232' AS nvarchar(10)), CAST('2004102881010' AS varchar(50))
)
SELECT TableA.*
FROM TableA
INNER JOIN TableB
ON TableA.PK = TableB.FK
WHERE TableA.Field1 > TableB.Field2
Results
PK Field1
0908232 2005102881010
This seems like a problem with missing zeroes:
20041028*0*81010
There is nothing wrong with your query, but your data.
Consider 2001-01-01 01:01:01, this would be seen as: 200111111
It should be seen as: 20010101010101
Comparrison operators (>, <) used on strings (varchars, nvarchars, etc.) work alphabetically. For example, '9' > '11' is true. You might try doing a data type conversion...
WHERE cast(A.field1 as int) > cast(B.field2 as int)

in sqlserver, need to select one of two columns, can a case statment do this?

My table:
Users (userID, col1, col2)
I want to make a generic stored procedure, but I need to return EITHER col1 or col2 in a query.
Can I case statement handle this situation?
SELECT userID, col1
FROM Users
OR
SELECT userID, col2
FROM Users
Using CASE:
SELECT t.userid,
CASE
WHEN [something to evaluate why to show col1 vs col2 ] THEN
t.col1
ELSE
t.col2
END
FROM USERS t
Using COALESCE:
SELECT t.userid,
COALESCE(t.col1, t.col2)
FROM USERS t
COALESCE returns the first column value that isn't null, starting from the left.
Yes, as long as you don't mind returning the same column names:
SELECT userID, ArbitraryCol = CASE WHEN #param = 1 then col1 ELSE col2 END
FROM Users
If you need the column headers to change, then you should use the IF statement
IF #param = 1
BEGIN
SELECT userID, col1 FROM Users
END
ELSE
BEGIN
SELECT userID, col2 FROM Users
END
I think SQL Server 2000/2005 is something like this.
select
UserID,
case UserID
when 1 then Col1
when 2 then Col2
else 'boo'
end as SpecialSituation
from
Users
It can, assuming you have a logical expression for when to return col1 instead of col2:
SELECT USERID CASE WHEN USERTYPE='X' THEN COL1 ELSE COL2 END FROM USERS
If col1 and col2 are of different types, you will need to use CAST or CONVERT to convert one to the other.

Resources