Decode in oracle, with multiple condition - sql

Select decode(a.Type,1,'ONE',2,'TWO',null ,'OTHER')||
Decode (b.Active, 1 ,'Yes',0,'NO', null ,'NO'),
count(*)
from TypeTable a,
Status b
where a.id=b.id
and a.type in(12,3,34,45,66);
Now question is,
I want to count those who has type 1 and other that in record
Like
Column1 | Column2
---------------+----------
One | 10
ONE
Other that ONE | 20

I'm not sure what do you want. Maybe you looking for something similar to my example.
select decode(object_type,'SYNONYM','SYNONYM','OTHER THAN SYNONYM') column1, count(*) column2 from user_objects
group by decode(object_type,'SYNONYM','SYNONYM','OTHER THAN SYNONYM');

Related

If I have two columns, how can I select all distinct values of columnA where columnB is never a specific value given that columnA is the same value?

So let's say I have two columns:
A
B
1
300
1
299
2
300
2
300
3
299
3
299
I want to look for distinct values of A such that there is never a combination of A and B where B equals 300.
In my example, I would want to return the columnA value 3.
Result
A
3
How do I accomplish this with SQL?
What you are looking for is called conditional aggregation. You want to aggregate by A (i.e. show A values in your result) and have a check only applied on particular B values. For instance:
select a
from mytable
group by a
having count(case when b = 300 then 1 end) = 0;
A simple subquery will give the results.
Exclude the Rows using the NOT IN keyword
SELECT DISTINCT ColumnA
FROM TABLE
WHERE ColumnA NOT IN(
SELECT ColumnA FROM Table WHERE ColumnB=300)
You can also use NOT EXISTS
SELECT DISTINCT A
FROM tbl t1
WHERE NOT EXISTS(
SELECT 1 FROM Tbl t2 WHERE t2.A=t1.B AND t2.B=300)

Get result true if all the rows have met the condition in sql

Basically i'm looking for solution for the condition, where table has the following rows and i want to select only those where condition is met by all the rows.
ID category flag
1 A 1
2 A 1
3 A 0
4 B 1
5 C 0
Expected Result is B where flag is true for its category.
I hope that my answer would be helpful to your problem. In the subquery, a list of the categories is created by filtering the flags.
SELECT *
FROM tablename a
WHERE a.category NOT IN (
SELECT b.category
FROM tablename b
WHERE b.flag=0)
You want the categories for which the minimum flag is 1 (meaning there is no flag = 0):
select category
from tablename
group by category
having min(flag) = 1
See the demo.
Results:
| category |
| -------- |
| B |
Use correlated subquery with not exists
select * from tablename a
where not exists (select 1 from tablename b where a.category=b.cateogry and flag=0)
Try this
select distinct category,flag from test where category in
(select t.category from (select category,flag from test
group by category,flag)t group by t.category having count(*)=1)
and flag=1;
If you have a separate table of categories, then not exists is often the fastest method:
select c.*
from categories c
where not exists (select 1
from t
where t.category = c.category and
t.flag = 0
);
In particular, this can take advantage of an index on (category, flag). If you don't have such a table, then forpas's solution is quite effective.

How to order a string aggregation based on another column in postgresql?

So basically I have 2 polygon tables, tableA that I want to update with the aggregated strings from tableB. tableB has 2 columns
TableB is structure something like
viable | fruit_id
yes | banana1
no | apple2
maybe | watermelon1
no | peach3
My update query looks like:
update TableA a set
fruitids = (select string_agg(fruit_id, ', ' order by fruit_id)
from tableB b st_contains(b.geom, a.geom))
But this will just return me the fruit ids in alphabetical order. How can I make it so that it will list the viable ones first? In this case my intended output would be:
banana1, watermelon1, apple2, peach3
you can use conditional sorting:
select string_agg(fruit_id, ', ' order by
case viable
when 'yes' then 1
when 'maybe' then 2
else 3
end,
fruit_id)
from tableB b st_contains(b.geom, a.geom)

SQL simplifying an except query

I have a database with around 50 million entries showing the status of a device for a given day, simplified to the form:
id | status
-------------
1 | Off
1 | Off
1 | On
2 | Off
2 | Off
3 | Off
3 | Off
3 | On
...
such that each id is guaranteed to have at least 2 rows with an 'off' status, but doesn't have to have an 'on' status. I'm trying to get a list of only the ids that do not have an 'On' status. For example, in the above data set I'd want a query returned with only '2'
The current query is:
SELECT DISTINCT id FROM table
EXCEPT
SELECT DISTINCT id FROM table WHERE status <> 'Off'
Which seems to work, but it's having to iterate over the entire table twice which ends up taking ~10-12 minutes to run per query. Is there a simpler way to do this with only a single query?
You can use WHERE NOT EXISTS instead:
Select Distinct Id
From Table A
Where Not Exists
(
Select *
From Table B
Where A.Id = B.Id
And B.Status = 'On'
)
I would also recommend looking at the indexes on the Status column. 10-12 minutes to run is excessively long. Even with 50m records, with proper indexing, a query like this shouldn't take longer than a second.
To add an index to the column, you can run this (I'm assuming SQL Server, your syntax may vary):
Create NonClustered Index Ix_YourTable_Status On YourTable (Status Asc);
You can use conditional aggregation.
select id
from table
group by id
having count(case when status='On' then 1 end)=0
You can use the help of a SELF JOIN ..
SELECT DISTINCT A.Id
FROM Table A
LEFT JOIN Table B ON A.Id=B.Id
WHERE B.Status='On'
AND B.Id IS NULL

Oracle SQL - filter out partitions or row groups that contain rows with specific value

I'm trying to solve the following: the data is organized in the table with Column X as the foreign key for the information (it's the ID which identifies a set of rows in this table as belonging together in a bundle, owned by a particular entity in another table). So each distinct value of X has multiple rows associated with it here. I would like to filter out all distinct values of X that have a row associated with them containing value "ABC" in Column Q.
i.e.
data looks like this:
Column X Column Q
-------- ---------
123 ABC
123 AAA
123 ANQ
456 ANQ
456 PKR
579 AAA
579 XYZ
886 ABC
the query should return "456" and "579" because those two distinct values of X have no rows containing the value "ABC" in Column Q.
I was thinking of doing this with a minus function (select distinct X minus (select distinct X where Q = "ABC")), as all I want are the distinct values of X. But i was wondering if there was a more efficient way to do this that could avoid a subquery? If for example I could partition the table over X and throw out each partition that had a row with the value "ABC" in Q?
I prefer to answer questions like this (i.e. about groups within groups) using aggregation and the having clause. Here is the solution in this case:
select colx
from data d
group by colx
having max(case when colq = 'ABC' then 1 else 0 end) = 0
If any values of colx have ABC, then the max() expression returns 1 . . . which does not match 0.
This should work:
SELECT DISTINCT t.ColX
FROM mytable t
LEFT JOIN mytable t2 on t.colx = t2.colx and t2.colq = 'ABC'
WHERE t2.colx IS NULL
And here is the SQL Fiddle.
Good luck.
How about this, using IN?
SQLFIDDLE DEMO
select distinct colx from
demo
where colx not in (
SELECT COLX from demo
where colq = 'ABC')
;
| COLX |
--------
| 456 |
| 579 |
Try this:
select DISTINCT colx
from demo
where colq not like '%A%'
AND colq not like '%B%'
AND colx not like '%C%'
SQL Fiddle