Want to exclude distinct values that relate to a value in another column of the table in sql - sql

I'm not sure I can do this in sql but the problem I'm running into is that I have one column which has names that relate to many values in another column. What i'm trying to do is only show names that do not relate to one of the values in the other column. I can't just exclude that value because the name appears in multiple rows. Is there a way to do this or do I need to use something like Python? Thanks in advance?
Names
Values
ps1234
value 1
ps1234
value 2

If I understand correctly, you want not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.name = t.name and t2.value = ?
);
The ? is a parameter placeholder for the value that you want no names for.

Related

How to make a new column in SELECT clause and fill it with a string/list dynamically with concat of all condition statements satisfied?

So there are two tables in a database. I have to find out whichever rows have discrepancy based on certain conditions (in couple of cases that's just equality checking between fields). I report ID of those rows.
The problem is to also include the reasons in another column as to why that ID is reported. Because an id can be fail multiple conditions (like mismatch on two fields), I just wanted to include all of those reasons in another column.
Basic idea is to append all the mismatches in another column.
I've looked at several SO questions but they don't exactly my use case. So now I'm thinking it's not possible with SQL.
I searched Google for "enter dynamic column values based on conditions sql", and hit : SQL Conditional column data return in a select statement : This adds a static column
I also learned it's possible to add another column in SELECT with dynamic content like this:
SELECT id, CASE
WHEN columnname "DEF" then "I" ELSE "YOU" newColumnName
FROM tableName
But I have not been able to find dynamic column value assignment and update SQL. That's the problem.
Expected results:
I just want to be able to concat all the cases "strings" which a record is applicable for.
Do this with the two tables.
So because I have two tables to work with I have to put these conditions in the WHERE sub-clause, and not in the SELECT one.
So, if for ID = 345, column "FOO_MAN" does not match between two tables, and column "BAR_TOO" also does not match between two tables, then?
Then I want my select clause to capture information like this:
ID | REASON
345 | FOO_MAN BAR_TWO
It's probably easier to build this type of query dynamically (e.g. using a stored procedure) based on the conditions you want to test, but here is a small example which shows how it can be done:
SELECT t1.id,
CONCAT_WS(' ',
CASE WHEN t1.foo != t2.foo THEN 'foo' END,
CASE WHEN t1.bar != t2.bar THEN 'bar' END
) AS reason
FROM t1
JOIN t2 ON t2.id = t1.id
WHERE t1.foo != t2.foo OR t1.bar != t2.bar
Output (for my demo on dbfiddle)
id reason
2 foo
4 bar
5 foo bar

Compare one value of column A with all the values of column B in Hive HQL

I have two columns in one table say Column A and Column B. I need to search each value of Column A with All the values of column B each and every time and return true if the column A value is found in any of the rows of column B. How can i get this?
I have tried using the below command:
select column _A, column_B,(if (column_A =column_B), True, False) as test from sample;
If i use the above command, it is checking for that particular row alone. But I need true value, if a value of column A is found in any of the rows of column B.
How can i can check one value of column A with all the all the values of column B?
Or Is there any possibility to iterate and compare each value between two columns?
Solution
create temporary table t as select rand() as id, column_A, column_B from sample; --> Refer 1
select distinct t3.id,t3.column_A,t3.column_B,t3.match from ( --> Refer 3
select t1.id as id, t1.column_A as column_A, t1.column_B as column_B,--> Refer 2
if(t2.column_B is null, False, True) as match from t t1 LEFT OUTER JOIN
t t2 ON t1.column_A = t2.column_B
) t3;
Explanation
Create an identifier column to keep track of the rows in original table. I am using rand() here. We will take advantage of this to get the original rows in Step 3. Creating a temporary table t here for simplicity in next steps.
Use a LEFT OUTER JOIN with self to do your test that requires matching each column with another across all rows, yielding the match column. Note that here multiple duplicate rows may get created than in Sample table, but we have got a handle on the duplicates, since the id column for them will be same.
In this step, we apply distinct to get the original rows as in Sample table. You can then ditch the id column.
Notes
Self joins are costly in terms of performance, but this is unavoidable for solution to the question.
The distinct used in Step 3, is costly too. A more performant approach would be to use Window functions where we can partition by the id and pick the first row in the window. You can explore that.
You can do a left join to itself and check if the column key is null. If it is null, then that value is not found in the other table. Use if or "case when" function to check if it is null or not.
Select t1.column_A,
t1.column_B,
IF(t2.column_B is null, 'False', 'True') as test
from Sample t1
Left Join Sample t2
On t1.column_A = t2.column_B;

Comparing the row with other row within same query

I have a question about the SQL Query.
Basically, I would like to get a sample value from the testCategory = compareTestCat and testType = compTestType.
I am not really sure if we can compare the first row with the fourth row within the same query.
Is there any way that I can do this?
Try SELF JOIN to compare values within the same table.
Try the Following:
SELECT A.*
FROM YourTable A
JOIN YourTable B ON A.testCategory = B.compareTestCat and A.testType = B.compTestType
A and B are the different alias names for the same table.
Based on the very sparse information you provided, this looks like what you need:
SELECT *
FROM
TestTable
WHERE
testCategory = compareTestCat
AND testType = compTestType;
UPDATE
If you are interested in comparing different rows in the same table with each other, then you will need to go with a self join on the table. Examples of solutions for this have already been provided by others.

SQL: How to update an empty column with pre-defined set of values

I have a table with, let's say, 100 records. The table has two columns. The first column (A) has unique values. The second column (B) has NULL values
For 4 elements from column A I'd like to associate some earlier defined values, and they are unique as well.
I don't care about which value from column B will be associated with the value from column A. I'd like to associate 4 unique values with another 4 unique values. Basically, like I'd cut and paste a block of values from one column to another in excel.
How can I do it without using cursors?
I'd like to use one Update statement for ALL rows instead one Update statement for EVERY row as I do now.
Try this:
UPDATE t
SET ColumnB = BValue
FROM Table t
INNER JOIN
(
SELECT 1 AValue, 'Mouse' BValue UNION
SELECT 2, 'Cat' UNION
SELECT 3, 'Dog' UNION
SELECT 4, 'Wolf'
) PreDefined ON(t.ColumnA = PreDefined.AValue)
Use any number you want in the 'PreDefined' table, as long as they are unique and within the range of values in columnA of your original table.
If you are only trying to fill a table for testing purposes, I guess you could:
A) Use the value from Column A itself (as it is already unique).
B) If they are to be different, use some function on the column A's value to obtain a column B value (something simple, like (ColumnA * 10), and this would give youA)
C) Create a temp table with a "dictionary" setting a B value for each possible A value, and then update the rows desired on your table looking up from values on this dictionary table.
Anyway, if you explain a little further your purpose it will be easier to try suggesting you a solution.
if your animal data is already in a database table, then you can use a single update statement like this:
update target_table t4
set columnb = (
select animal_name
from (select columna, animal_name
from (select rownum rowNumber, animal_name from animal_table) t1
join (select rownum rowNumber, columna from target_table t1 where columnb is null) t2
on t1.rowNumber = t2.rowNumber
) t3
where t4.columna = t3.columna
)
;
this works by selecting a sequence number and animal name from the source table, then selecting a sequence number and columna value from your target table. by joining those records on the sequence number you guarantee you get exactly 1 animal name for each columna value. you can then join those columna-to-animal records to your target table to do an update of columnb.
for more background on updating one table from values in another, you might consider the solutions presented here: Update rows in one table with data from another table based on one column in each being equal. the only difference is that in your example, you do not have any column that matches between your target table and your animal names table, so you need to use the rownum to create an arbitrary 1-to-1 matching of records.
if your unique options are in a text file or spreadsheet, then you can format them into a fixed-width space-padded string and pick the one you want using the rownum index like so:
update table_name
set columnb = trim(substr('mouse cat dog wolf ', rownum*6-6, 6))
where columnb is null;

Compare comma separated list with individual row in table

I have to compare comma separated values with a column in the table and find out which values are not in database. [kind of master data validation]. Please have a look at the sample data below:
table data in database:
id name
1 abc
2 def
3 ghi
SQL part :
Here i am getting comma separated list like ('abc','def','ghi','xyz').
now xyz is invalid value, so i want to take that value and return it as output saying "invalid value".
It is possible if i split those value, take it in temp table, loop through each value and compare one by one.
but is there any other optimal way to do this ??
I'm sure if I got the question right, however, I would personally be trying to get to something like this:
SELECT
D.id,
CASE
WHEN B.Name IS NULL THEN D.name
ELSE "invalid value"
END
FROM
data AS D
INNER JOIN badNames B ON b.Name = d.Name
--as SQL is case insensitive, equal sign should work
There is one table with bad names or invalid values if You prefer. This can a temporary table as well - depending on usage (a black-listed words should be a table, ad hoc invalid values provided by a service should be temp table, etc.).
NOTE: The select above can be nested in a view, so the data remain as they were, yet you gain the correctness information. Otherwise I would create a cursor inside a function that would go through the select like the one above and alter the original data, if that is the goal...
It sounds like you just need a NOT EXISTS / LEFT JOIN, as in:
SELECT tmp.InvalidValue
FROM dbo.HopeThisIsNotAWhileBasedSplit(#CSVlist) tmp
WHERE NOT EXISTS (
SELECT *
FROM dbo.Table tbl
WHERE tbl.Field = tmp.InvalidValue
);
Of course, depending on the size of the CSV list coming in, the number of rows in the table you are checking, and the style of splitter you are using, it might be better to dump the CSV to a temp table first (as you mentioned doing in the question).
Try following query:
SELECT SplitedValues.name,
CASE WHEN YourTable.Id IS NULL THEN 'invalid value' ELSE NULL END AS Result
FROM SplitedValues
LEFT JOIN yourTable ON SplitedValues.name = YourTable.name