SQL to fetch Unique values based on condition - sql

I have below data. The condition is that if the Id has two different types then take Long, such that there should not be any duplicate Id's
**id type**
1 Short
1 Long
2 Short
3 Short
3 Long
4 Short
And i need output like this.
**id type**
1 Long
2 Short
3 Long
4 Short

Does this work for you:
select id,
case when count(id) > 1 then 'Long' else 'Short' end as type
from tmp
group by id

You can simply take MIN from your Type column's value using GROUP BY on ID column. No CASE or COUNT statement is required. This following script will always work if you have specific value "short" and "long" in your column Type.
SELECT ID,MIN(Type) Type
FROM your_table
GROUP BY ID

You can do this:
Select id, case when count(id)>1 then 'Long' else min(Type) End as Type
from Tbl
group by id

Related

Filter by one column then count unique value in another column in SQL

I would like to filter data by column Base =1 and then count the number of unique values in another column 'Animal' in SQL, data:
Animal Base Value
1 A 1 X
2 B 1 X
3 A 2 Y
4 A 3 V
Expected output in this case is 2 from the first two rows.
Simpler than you may have thought:
SELECT count(DISTINCT Animal)
FROM tbl
WHERE Base = 1;
Should work in any halfway decent RDBMS including your undisclosed one. (You may have to enclose column names in double-quotes.)
This should do it, assuming the table is named animals:
select count(*) from (select distinct Animal from animals where Base=1) tb1;

How to return all records having only integer values in a specific column?

I want to return all records where a certain column has only integer values.
For example,
parent_id category_id
1 43656
2 aabc6gn
3 1123
4 aaxxyy
The result should be -
parent_id category_id
1 43656
3 1123
Below is for BigQuery Standard SQL
#standardSQL
select *
from yourTable
where not regexp_contains(category_id, r'[^\d]')
if to applied to sample data from your question - output is
Use REGEXP_MATCH here:
SELECT parent_id, category_id
FROM yourTable
WHERE REGEXP_MATCH(category_id, r'^[0-9]+$');
You can do this by attempting to convert to an integer:
where safe.convert(category_id as int64) is not null
I interpret your question as saying that the value can be converted to an integer, not that every digit is an integer.
If the latter, I would simply use:
where regexp_contains(category_id, '^[0-9]+$')

Returning several values within a CASE expression in subquery and separate columns again in main query

My test table looks like this:
# select * from a;
source | target | id
--------+--------+----
1 | 2 | 1
2 | 3 | 2
3 | 0 | 3
My query is this one:
SELECT *
FROM (
SELECT
CASE
WHEN id<>1
THEN source
ELSE 0
END
AS source,
CASE
WHEN id<>1
THEN target
ELSE 0
END
AS target
FROM a
) x;
The query seems a bit odd because the CASE expression with the same criteria is repeated for every column. I would like to simplify this and tried the following, but it doesn't work as expected.
SELECT *
FROM (
SELECT
CASE
WHEN id<>1
THEN (source, target)
ELSE (0, 0)
END
AS r
FROM a
) x;
It yields one column with a row value, but I would rather get the two original columns. Separating them with a (r).* or similar doesn't work, because the "record type has not been registered".
I found several questions here with solutions regarding functions returning RECORD values, but none regarding this example with a sub-select.
Actually, there is a quite long list of columns, so repeating the same CASE expression many times makes the whole query quite unreadable.
Since the real problem - as opposed to this simplified case - consists of several CASE expressions and several column groups, a solution with a UNION won't help, because the number of UNIONs would be large and make it unreadable as well as several CASEs.
My actual question is: How can I get the original columns from the row value?
This answers the original question.
If I understood your needs, you want 0 and 0 for source and target when id = 1:
SELECT
0 AS source,
0 AS target
FROM tablename
WHERE id = 1
UNION ALL
SELECT
source,
target
FROM tablename
WHERE id <> 1
Revised answer: You can make your query work (fixing the record type has not been registered issue) by creating a TYPE:
CREATE TYPE stpair AS (source int, target int);
And cast the composite value column to that type:
SELECT id, (cv).source, (cv).target
FROM (
SELECT id, CASE
WHEN id <> 1 THEN (source, target)::stpair
ELSE (0, 0)::stpair
END AS cv
FROM t
) AS x
Having said that, it should be far more convenient to use arrays:
SELECT id, av[1] AS source, av[2] AS target
FROM (
SELECT id, CASE
WHEN id <> 1 THEN ARRAY[source, target]
ELSE ARRAY[0, 0]
END AS av
FROM t
) AS x
Demo on db<>fiddle
Will this work for you?
select source,target,id from a where id <>1 union all select 0 as source,0 as target,id from a where id=1 order by id
I have used union all to included cases where multiple records may have ID=1

Find certain values and show corresponding value from different field in SQL

So I found these 2 articles but they don't quite answer my question...
Find max value and show corresponding value from different field in SQL server
Find max value and show corresponding value from different field in MS Access
I have a table like this...
ID Type Date
1 Initial 1/5/15
1 Periodic 3/5/15
2 Initial 2/5/15
3 Initial 1/10/15
3 Periodic 3/6/15
4
5 Initial 3/8/15
I need to get all of the ID numbers that are "Periodic" or NULL and corresponding date. So I want a to get query results that looks like this...
ID Type Date
1 Periodic 3/5/15
3 Periodic 3/6/15
4
I've tried
select id, type, date1
from Table1 as t
where type in (select type
from Table1 as t2
where ((t2.type) Is Null) or "" or ("periodic"));
But this doesn't work... From what I've read about NULL you can't compare null values...
Why in SQL NULL can't match with NULL?
So I tried
SELECT id, type, date1
FROM Table1 AS t
WHERE type in (select type
from Table1 as t2
where ((t.Type)<>"Initial"));
But this doesn't give me the ID of 4...
Any suggestions?
Unless I'm missing something, you just want:
select id, type, date1
from Table1 as t
where (t.type Is Null) or (t.type = "") or (t.type = "periodic");
The or applies to boolean expressions, not to values being compared.

How to sort combination of integer and text in PostgreSQL?

I have this table
id value
1 OK
2 xminimum
3 NO
4 YES
I want to sort this table by value where minimum is always first then the rest according to alphabetic order of value column
Meaning:
xminimum
NO
OK
YES
I wrote this query:
Select *
from table_a
order by case when value='xminimum' then 1 else ????? end
I don't know what to put in the else... conceptually it should be else value end so it means alphabetic order.. but I can not combine integer with text.
How do I fix it?
As requested, copied from my comment:
Select *
from table_a
order by case when value='xminimum' then 1 else 2 end, value
Another solution:
SELECT *
FROM table_a
ORDER BY value <> 'xminimum', value;
Do it like you have and add the value column as second column to sort by:
SELECT *
FROM table_a
ORDER BY CASE WHEN value='xminimum' THEN 1 ELSE 2 END, value