Oracle SQL - A count that excludes completely a Key with the if not equal statement - sql

Ok here goes:
MyTableName
KEY Value1
1 ABC
1 DEF
1 GHI
2 ABC
2 DEF
2 YUI
I have a child table that is linked via a Key (stated above)
I need to find records, linked to the parent table (i have no issues with my join) where value 1 meets conditions and does not meet certain conditions.
So, for my Example, I want to retrieve the value '1' from the "KEY" above, because my need is where value 1 = 'ABC' or value 1 = 'DEF' but value 1 != YUI,
so I would want '1' to come back, but not 2
SELECT KEY, count(*)
FROM MyTableName
WHERE (value1 = 'ABC'
OR value1 = 'DEF')
AND value1 != 'YUI'
GROUP BY KEY
HAVING count(KEY) = 2
The above statement, find both Key 1 and 2, where I need it only to find Key 1.
Can anyone help?

Use the HAVING clause with conditional counts:
select key
from mytablename
group by key
having count(case when value1 in ('ABC','DEF') then 1 end) > 0
and count(case when value1 = 'YUI' then 1 end) = 0;
(You can add where value1 in ('ABC','DEF','YUI'), which may speed up the query, because you are not interested in rows containing other values.)
(Some people prefer to include an explicit else branch: count(case when value1 = 'YUI' then 1 else null end) and others prefer sum(case when value1 = 'YUI' then 1 else 0 end). That's a matter of personal preference.)

Related

Count the no of columns with same value in SQL

I have a database MySQL table as following
Id
Column1
Column2
Column3
First
value1
value1
value2
Second
value2
value1
value2
I want to retrieve the count of value1 for the row with id First example table as follows
Id
COUNT(value1)
First
2
I searched on google but found posts only regarding counting in one specific column.
Can anyone help me with the SQL query for retrieving the above type.
Use a case expression to determine for each column whether to count it or not e.g.
select
case when Column1 = 'value1' then 1 else 0 end
+ case when Column2 = 'value1' then 1 else 0 end
-- ...
from MyTable
where id = 'first'

SQL query to fetch the result set with same status

The table 1 is as follows,
ID
FK1_ID
FK2_ID
1
1
1
2
1
2
3
1
3
The table with FK2 is as follows,
ID
Type
Status
1
Type1
True
2
Type2
True
3
Type1
False
The FK2_ID column is the ID column of table 2.
The expected result is, for any FK1_ID(which I have as a list of IDs), need to check all its FK2 entries in the 2nd table of Type1 and status True.
For example:
Here, I want to return YES, if all the Type1 entries are True for the specific FK1_ID. Else NO.
So, for FK1_ID with 1, the FK2 table has 3 records. Of which Type1 has 2 records. I should return YES, if both Type1 records are True, else NO.
I want accomplish this using SQL.
Any help is appreciated?
Looks like you just need to compare a conditional count of Status to the full count, with a CASE for the final result.
SELECT
t1.FK1_ID,
Result = CASE WHEN COUNT(*) = COUNT(CASE WHEN FK2.Status = 'True' THEN 1 END)
THEN 'Yes'
ELSE 'No' END
FROM table1 t1
JOIN FK2 ON FK2.ID = t1.FK2_ID
AND FK2.Type = 'Type1'
GROUP BY
t1.FK1_ID;
A slightly shorter but less understandable version
CASE WHEN COUNT(*) = COUNT(NULLIF(FK2.Status, 'False'))
Alternatively
CASE WHEN COUNT(NULLIF(FK2.Status, 'True')) = 0
I'm not totally following your logic (how these two tables are joined) but sounds like you want to compare a total count with a conditional count so maybe something like
with t as (select type, count(status) as cnt,
sum(case when status ='True' then 1 else 0 end) as truecnt
from FK2
group by type)
select type, case when truecnt > 0 and cnt = truecnt then 'Yes' else 'No' end as MyResult
from t

Get a particular record based on a condition in SQL

My requirement is to get id for missing status from SQL table. I will get a list of status for each id, say A,B,C,D. In a scenario, I have to check status B exists or not. Table gets updated everyday and each time new Id will be created
Conditions,
If status A exists and other statuses such as C and D does not
exists, then don't need to get id.
If status A and B exists and other statuses such as C or D does not exists, then don't need to get id .
If status A exists and B not exists, other
statuses such as C or D exists, then I should get the id of that
record
If status A and B exists, other
statuses such as C or D exists (all status exists), then I don't need to get the id of that
record
Table1:
Id StatusCode
1 A
1 C
2 A
2 B
2 C
3 A
3 C
3 D
How do I get Id 1 and 3 using SQL query?, Seems simple but as I am new to SQL I could not able to get it in SQL.
select statement in this screenshot works fine when there is only one id, it fails on multiple id. I tried many other way, but no use
Try this
SELECT DISTINCT ID
FROM T1
WHERE Statuscode = 'A' AND ID NOT IN (SELECT ID FROM T1 WHERE Statuscode = 'B' )
AND (ID IN (SELECT ID FROM T1 WHERE Statuscode = 'C' ) OR ID IN (SELECT ID FROM T1 WHERE Statuscode = 'D' ))
FIDDLE DEMO
Also, To correct Gordon Linoff's answer, we need to add one more where criteria there
SELECT Id
FROM T1
GROUP BY Id
HAVING SUM(CASE WHEN Statuscode = 'A' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN Statuscode = 'B' THEN 1 ELSE 0 END) = 0 AND
SUM(CASE WHEN Statuscode IN ('C', 'D') THEN 1 ELSE 0 END) > 0;
FIDDLE DEMO
This answers the original version of the question.
I think you can use aggregation:
select id
from t
group by id
having sum(case when status = 'A' then 1 else 0 end) > 0 and
sum(case when status in ('C', 'D') then 1 else 0 end) > 0;
SELECT id
FROM t
GROUP BY
Id
HAVING MAX(status) = CHAR(64 + COUNT(*))
--char(64+1) = A, char(64+2) = B etc
The logic behind this is that it will take all count the same types of id. So if you have 3 rows you will need abc. If you have an id with 4 rows you will have ABCD. Generally the max status should always be the same as the number of rows.
This is true of course if you have no duplicate between id and status code.
select distinct id from t where t.statuscode = 'C' or t.statuscode = 'D' group by t.id

Impala SQL, return value if a string exists within a subset of values

I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t

Update column in set of records only if multiple rows exist with a given value in a different field?

My_Table would be something like this:
user_id shared_field bool_field
------- ------------ ----------
1 abc null
2 def null
3 ghi Y
4 ghi null
5 ghi null
6 abc Y
7 jkl null
If the bool_field changes for a user who shares the same shared_field with other users (such as user_id 3, 4, and 5 above), only that one user should have a 'Y'. The rest should have null values in the bool_field column. For example, if user_id 4 should now have the 'Y', I have to change user_id 4's bool_field to 'Y', and ensure that user_id 3 and 5 have bool_field values of null.
If the user doesn't share a shared_field value with anyone else, then that bool_field should be null (as in user_id 1 and 2 above).
Update: added a couple of lines to show that multiple user_ids could share a given shared_field (eg, 1 and 6 both have 'abc'; 3, 4, and 5 all have 'ghi' - only one 'abc' user should have a 'Y', and only one 'ghi' user should have a 'Y' and so on, while the rest have null in their bool_field column; user_ids that don't share a shared_field value, such as user_ids 2 and 7, should all have null in their bool_field column.) Clear as mud, right? ;)
This statement works:
UPDATE my_table
SET bool_field = (CASE
WHEN user_id = 4 THEN 'Y'
ELSE NULL
END)
WHERE shared_field = 'ghi'
AND (SELECT COUNT(shared_field)
FROM my_table
WHERE shared_field = 'ghi') > 1;
The question: is there some way that I can accomplish this same thing without knowing the shared_field value in advance? For example (and this doesn't work, of course) - Update: "of course" means I know this doesn't work because it is not correct Oracle syntax! The point is to give an idea of what I'm trying to do.
UPDATE my_table
SET bool_field = (CASE
WHEN user_id = 4 THEN 'Y'
ELSE NULL
END)
WHERE shared_field = (SELECT shared_field FROM my_table WHERE user_id = 4) as sharedVal
AND (SELECT COUNT(shared_field)
FROM my_table
WHERE shared_field = sharedVal) > 1;
Update: this is a regular SQL statement - I can't use a stored procedure.
First, rather than saying that something "doesn't work", it is generally helpful to tell us how it doesn't work. The query you posted, for example, appears to have syntax errors (as sharedVal is invalid because you can't assign an alias to an expression you're computing in the SELECT list). But it's not clear if "doesn't work" means that you're getting syntax errors (which we can relatively easily debug with the error message) or whether it means that the query runs but doesn't do what you want (which I would expect the query to do if the syntax errors were corrected) in which case knowing how the query isn't doing what you want would be helpful.
I would expect something like
UPDATE my_table a
SET bool_field = (CASE WHEN user_id = 4
THEN 'Y'
ELSE NULL
END)
WHERE shared_field = (SELECT shared_field
FROM my_table b
WHERE b.user_id = 4)
AND EXISTS( SELECT 1
FROM my_table c
WHERE a.shared_field = c.shared_field
AND a.user_id != c.user_id )
to work assuming that user_id is the primary key.
It's been awhile since I've worked on Oracle, so check to make sure that this query returns the list of records you want to update:
SELECT *
FROM my_table m
WHERE EXISTS (SELECT 1
FROM my_table
WHERE shared_field = m.shared_field
HAVING COUNT(shared_field) > 1);
If so, then this should work:
UPDATE my_table
SET bool_field = (CASE
WHEN user_id = 4 THEN 'Y'
ELSE NULL
END)
WHERE EXISTS (SELECT 1
FROM my_table
WHERE shared_field = m.shared_field
HAVING COUNT(shared_field) > 1);
You could also try this WHERE clause:
WHERE shared_field IN (SELECT shared_field
FROM my_table
GROUP BY shared_field
HAVING COUNT(shared_field) > 1);