Excluding Records Based on Another Column's Value - sql

I'm working in Redshift and have two columns from an Adobe Data feed:
post_evar22 and post_page_url.
Each post_evar22 has multiple post_page_url values as they are all the pages that the ID visited.
(It's basically a visitor ID and all the pages they visited)
I want to write a query where I can list distinct post_evar22 values that have never been associated with a post_page_url that contains '%thank%' or '%confirm%'.
In the dataset below, ID1 would be completely omitted from the query results bceause it was associated with a thank-you page and a confirmation page.

This is a case for NOT EXISTS:
select distinct post_evar22
from table t1
where not exists (
select 1
from table t2
where t2.post_evar22 = t1.post_evar22
and (t2.post_page_url like '%thank%' or t2.post_page_url like '%confirm%')
)
Or MINUS if your dbms supports it:
select post_evar22 from table
minus
select post_evar22 from table where (post_page_url like '%thank%' or post_page_url like '%confirm%')

Seems fairly straight forward. Am I missing something?
SELECT DISTINCT post_evar22
FROM table
WHERE post_page_url NOT LIKE '%thank%'
AND post_page_url NOT LIKE'%confirm%

Related

Compare tables and Find the missing records

I am trying to compare a table T1 and a view v1 and find the missing records from the table T1 and display the results in a excel when a button is clicked. I am trying the wrap up the situation into a stored procedure and call it from vba code. I am not sure on how to start this.. The field names are different in both the tables, although it has same data. Any help will be much appreciated. I have tried many code samples , but I didn't achieve what I want..
Table T1
alpha.FileID
Master Policy Number
Insurance Name
View V1
FileID
PolNO
InsName
These are the few columns. Though, they have different field names, the data are the same. Some times the records are missing in the table v1, and I need to compare the two tables and find the missing records of the table v2.
SELECT View_v1.[Insured Name]
FROM View_v1
WHERE View_v1.alpha.FileID NOT IN
(
SELECT Table_t1.FileID
FROM Table_t1
)
An except clause is the easiest way to do this:
SELECT FileID, PolNO, InsName
FROM View V1
EXCEPT
SELECT FileID, MasterPolicyNumber, InsuranceName
FROM Table T1
This will give you the rows in the first select that do not exist in the second select (depending on your desired results you might flip the top and bottom selects). As long as the data types and number of columns are the same, the name of each field doesn't matter. Your result set will show the field names of the first select.
Also since you didn't specify your dbms, "MINUS" is used instead of "EXCEPT" for some dbms's like Oracle.
I believe this is what you're looking for based on your description.
I'm comparing every field, not just FileID as your example appears to be attempting. So, if you truly want to look only for missing FileIDs, just remove the other join on conditions.
SELECT View_v1.FileID, View_v1.PolNO, View_v1.InsName
FROM View_v1
LEFT JOIN Table_t1
on View_v1.FileID = Table_t1.FileID
and View_v1.PolNO = Table_t1.[Master Policy Number]
and View_v1.InsName = Table_t1.[Insurance Name]
WHERE Table_t1.FileID is null

SQL Contains query

I have two tables (A and B) that contain ID's however in table B some records have these ID's grouped together e.g the IDExec column may consist of a record that looks like 'id1 id2'. I'm trying to find the ID's in table A that do not appear in table B. I thought that by using something like:
SELECT *
FROM A
WHERE NOT EXISTS( SELECT *
FROM B
WHERE Contains(A.ExecID, B.ExecID))
This isn't working as contains needs the 2nd parameter to be string, text_lex or variable.
Do you guys have a solution to this problem?
To shed more light on the above problem the table strucutres are as follows:
Table A (IDExec, ProdName, BuySell, Quantity, Price, DateTime)
Table B (IDExec, ClientAccountNo, Quantity)
The C# code I've created to manipulate the buysell data in Table A groups up all the buysell's of the same product on a given day. The question now is how would you guy normalise this so I'm not bastardizing IDExec? Would it be better to create a new ID column in Table B called AllocID and link the two tables like that? So something like this:
Table A (IDExec, AllocID, ProdName, BuySell, Quantity, Price, DateTime)
Table B (AllocID, ClientAccountNo, Quantity)
This data should be normalized, storing multiple values in one field is a bad idea.
A workaround is using LIKE:
SELECT *
FROM A
WHERE NOT EXISTS( SELECT *
FROM B
WHERE ' '+B.ExecID+' ' LIKE '% '+A.ExecID+' %')
This is using space delimited values per your example.
This is kind of crude, but it will give you all of the entries in A that are not contained in B.
SELECT * FROM A WHERE A.ExecID not in (SELECT ExecID from B);
I have a very simple solution. It's called normalization. Proper modeling can work wonders for query simplicity and accuracy.
However, you may be stuck with what you have. Assuming ExecID is a string in both tables, try this:
select *
from A
where not exists(
select *
from B
where ExecID like '%' || a.ExecID || '%';
This is a horrible query as it performs a complete table scan of B for every row in A and the subquery is susceptible to false hits, so maybe you can do better, but your best course ultimately is a touch of database refactoring.

SQL Server where column in where clause is null

Let's say that we have a table named Data with Id and Weather columns. Other columns in that table are not important to this problem. The Weather column can be null.
I want to display all rows where Weather fits a condition, but if there is a null value in weather then display null value.
My SQL so far:
SELECT *
FROM Data d
WHERE (d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%' OR d.Weather IS NULL)
My results are wrong, because that statement also shows values where Weather is null if condition is not correct (let's say that users mistyped wrong).
I found similar topic, but there I do not find appropriate answer.
SQL WHERE clause not returning rows when field has NULL value
Please help me out.
Your query is correct for the general task of treating NULLs as a match. If you wish to suppress NULLs when there are no other results, you can add an AND EXISTS ... condition to your query, like this:
SELECT *
FROM Data d
WHERE d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'
OR (d.Weather IS NULL AND EXISTS (SELECT * FROM Data dd WHERE dd.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'))
The additional condition ensures that NULLs are treated as matches only if other matching records exist.
You can also use a common table expression to avoid duplicating the query, like this:
WITH cte (id, weather) AS
(
SELECT *
FROM Data d
WHERE d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'
)
SELECT * FROM cte
UNION ALL
SELECT * FROM Data WHERE weather is NULL AND EXISTS (SELECT * FROM cte)
statement show also values where Wether is null if condition is not correct (let say that users typed wrong sunny).
This suggests that the constant 'sunny' is coming from end-user's input. If that is the case, you need to parameterize your query to avoid SQL injection attacks.

MSSQL Full Text search - Search only part of table rows

Is there a way to limit the search to specific rows in a table.
For Example:
On a big table I want to search only on rows with a specific Company ID:
select *
from Actions
where Company_ID=1253
and CONTAINS(ItemDesc, 'ABC')
SELECT
AC.*,
col1.RANK
FROM Actions AC
INNER JOIN CONTAINSTABLE(Actions, ItemDesc, 'ABC',50) as col1
on col1.[KEY] = AC.ActionId
where Company_ID=1253
I tried both examples and I think the search runs first on all the table rows,
and then it filters by Company_ID
I'm looking for a way to limit the row number before search
Thanks.
How does something like this behave?
SELECT *
FROM
(
SELECT *
FROM Actions
WHERE Company_ID = 1253
) AS CompanyFilteredActions
WHERE CONTAINS(ItemDesc, 'ABC')
You'd need to look at query plans and performance, but I think this will at least do what you ask.

Postgres Query of an Array using LIKE

I am querying a database in Postgres using psql. I have used the following query to search a field called tags that has an array of text as it's data type:
select count(*) from planet_osm_ways where 'highway' = ANY(tags);
I now need to create a query that searches the tags fields for any word starting with the letter 'A'. I tried the following:
select count(*) from planet_osm_ways where 'A%' LIKE ANY(tags);
This gives me a syntax error. Any suggestions on how to use LIKE with an array of text?
Use the unnest() function to convert array to set of rows:
SELECT count(distinct id)
FROM (
SELECT id, unnest(tags) tag
FROM planet_osm_ways) x
WHERE tag LIKE 'A%'
The count(dictinct id) should count unique entries from planet_osm_ways table, just replace id with your primary key's name.
That being said, you should really think about storing tags in a separate table, with many-to-one relationship with planet_osm_ways, or create a separate table for tags that will have many-to-many relationship with planet_osm_ways. The way you store tags now makes it impossible to use indexes while searching for tags, which means that each search performs a full table scan.
Here is another way to do it within the WHERE clause:
SELECT COUNT(*)
FROM planet_osm_ways
WHERE (
0 < (
SELECT COUNT(*)
FROM unnest(planet_osm_ways) AS planet_osm_way
WHERE planet_osm_way LIKE 'A%'
)
);