How to use WHERE query at same column in same table? - sql

I have this data.
tbl_data
id value
1 A
1 B
1 C
2 A
2 C
I want to select id which have 'A' and 'B' as value.
SELECT id FROM tbl_data WHERE value = 'A' AND value = 'B'
But it returns zero result.
How to make it to return id 1 ?

select id from table
where
value in ('A', 'B')
group by id
having count( distinct value ) = 2

An alternative to the solution of #OTAR is to use a CTE
CREATE TEMPORARY TABLE t ( ID INT, value TEXT);
INSERT INTO t VALUES
(1,'A'),(1,'B'),(1,'C'),(2,'A'),(2,'C'),(2,'F');
WITH j AS (
SELECT id,array_agg(value) AS arr
FROM t GROUP BY id)
SELECT * FROM j
WHERE arr #> ARRAY['A','B'];
id | arr
----+---------
1 | {A,B,C}
(1 Zeile)

You can simply execute the following:
SELECT min(id) FROM table WHERE value in ('A','B');

Related

Getting all the values in one query that aren't in another with a group by

Given that I am using Redshift, how would I get the counts for a query that asks:
Given table A and table B, give me all the count of values in Table A for that grouping that aren't in table B;
So if table A and B look like:
Table A
Id | Value
==========
1 | "A"
1 | "B"
2 | "C"
And table B:
Id | Value
==========
1 | "A"
1 | "D"
2 | "C"
I would want:
Id | Count
==========
1 | 1
2 | 0
You can use left join and group by:
select a.id, sum( (b.id is null)::int )
from a left join
b
on a.id = b.id and a.value = b.value
group by a.id;
Use except and subquery
with a as
(
select 1 as id, 'A' as v
union all
select 1,'B'
union all
select 2,'C'
),b as
(
select 1 as id, 'A' as v
union all
select 1,'D'
union all
select 2,'C'
), c as
(
select id,v from a except select id,v from b
)
select id,sum ( (select count(*) from c where c.id=a.id and c.v=a.v))
from a group by id
output
id cnt
1 1
2 0
online demo which will work in redshift

SQL search for minimum values related to a table of duplicates

I have a SQL View that pumps out the following table, two columns
Column 1 Column 2
ID Value
1 10
1 12
1 15
2 3
2 6
I'd like to search for where record 1 returns it's minimum value (10) and record 2 returns it's minimum value (3)
Any help greatly appreciated.
SELECT
id
, MIN(value)
FROM yourview
GROUP BY id
You could try something like:
select [id], min([value]), max([value])
from viewname
group by id
order by id
The square brackets are SQL Server syntax to sidestep keywords; your database syntax may differ. What database are you using?
You could use Row_Number() OVER ().
; WITH cte AS (
SELECT id1 = 1, value = 10 UNION ALL
SELECT id1 = 1, value = 12 UNION ALL
SELECT id1 = 1, value = 15 UNION ALL
SELECT id1 = 2, value = 3 UNION ALL
SELECT id1 = 2, value = 6
)
SELECT z.id1, z.value
FROM (
SELECT id1, value, ROW_NUMBER() OVER ( PARTITION BY id1 ORDER BY value ASC ) AS rn
FROM cte
) z
WHERE z.rn = 1
Returns:
id1 value
1 10
2 3

SQL Query with group by clause, but counting two distinct values as if they were the same

I have a simple table with two columns, like the one below:
Id | Name
0 | A
1 | A
2 | B
3 | B
4 | C
5 | D
6 | E
7 | E
I want to make a SQL query which will count how many times each "Name" appears on the table. However, I need a few of these values to count as if they were the same. For example, a normal group by query would be:
select Name, count(*)
from table
group by Name
The above query would produce the result:
Name | Count
A | 2
B | 2
C | 1
D | 1
E | 2
but I need the query to count "A" and "B" as if they were only "A", and to count "D" and "E" as if they were only "D", so that the result would be like:
Name | Count
A | 4 // (2 "A"s + 2 "B"s)
C | 1
D | 3 // (1 "D" + 2 "E"s)
How can I make this kind of query?
You can make translation with case. Also, you can use subquery or CTE so you don't have to repeat yourself:
with cte as (
select
case Name
when 'B' then 'A'
when 'E' then 'D'
else Name
end as Name
from table
)
select Name, count(*)
from cte
group by Name
or with with online translation table:
select
isnull(R.B, t.Name), count(*)
from table as t
left outer join (
select 'A', 'B' union all
select 'E', 'D'
) as R(A, B) on R.A = t.Name
group by isnull(R.B, t.Name)
If you need A and B, D and E, to count the same, you can build a query like this:
SELECT
CASE Name WHEN 'B' THEN 'A' WHEN 'E' THEN 'D' ELSE Name END as Name
, COUNT(*)
FROM table
GROUP BY CASE Name WHEN 'B' THEN 'A' WHEN 'E' THEN 'D' ELSE Name END
Demo on sqlfiddle.
With a layer of abstraction and a CASE (SQL Fiddle example):
;WITH x AS
(
SELECT CASE Name WHEN 'B' THEN 'A'
WHEN 'E' THEN 'D'
ELSE Name
END AS Name
FROM Table1
)
SELECT Name, COUNT(1)
FROM x
GROUP BY Name
With a translation table (SQL Fiddle):
CREATE TABLE Translate(FromName char(1), ToName char(1));
INSERT INTO Translate VALUES ('B', 'A'), ('E', 'D');
SELECT COALESCE(t.ToName, a.Name) Name, COUNT(1)
FROM Table1 a
LEFT OUTER JOIN Translate t ON a.Name = t.FromName
GROUP BY COALESCE(t.ToName, a.Name)
FWIW, you can also do this with a VALUES derived table instead of a real table (SQL Fiddle):
SELECT COALESCE(t.ToName, a.Name) Name, COUNT(1)
FROM Table1 a
LEFT OUTER JOIN
(
VALUES ('B', 'A'),
('E', 'D')
) t(FromName, ToName) ON a.Name = t.FromName
GROUP BY COALESCE(t.ToName, a.Name)
this works
select t.a,count(t.id) from (
select case name when 'A' then 'A' when 'B' then 'A'
when 'C' then 'C' when 'D' then 'C'
when 'D' then 'D' when 'E' then 'D' end as A,id
from test) as t
group by A;

SQL return incremented number

Hi I want to create a SQL function to return either 1 if a name in a column is unique, otherwise if that name is not unique then return an increment of 1. Here is what it should look lile:
NAME | Number
A | 1
B | 1
C | 1
C | 2
C | 3
D | 1
E | 1
The problem I am having is getting the number to increment.
ANSI SQL:
select name,
row_Number() over (partition by name order by name) as number
from your_table
CREATE TABLE #TEST (NAME CHAR(1))
INSERT INTO #TEST
SELECT 'A'
UNION ALL
SELECT 'A'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'C'
UNION ALL
SELECT 'D'
SELECT NAME, ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY NAME) AS Number
FROM #TEST
If it's SQL Server, have a look here, at the Section C: Using ROW_NUMBER() with PARTITION:
http://msdn.microsoft.com/en-us/library/ms186734.aspx
SELECT
name
, ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) number
FROM tbl

Select data from table with update if particular row does not exist

I have a simple table TBL consisting of two columns Err_type and Val.
Need to select all date from it. Seems to be simple, but it gets uglier when particular row does not exist.
with cte as (
select TBL.Err_type, TBL.Val from TBL
where TBL.Err_type = 4 or TBL.Err_type = 2
)
select * from cte
There are possibilities that "4" or "2" might not exist in given datetime range. So i need to insert the missing row ("4" or "2" for Err_type and "0" for Val) and then get the table.
e.g.
Err_type | Val
---------------
4 | 50
2 | 0
instead of
Err_type | Val
---------------
4 | 50
Use following sql that will check for existence of record and if not found then insert.
WITH cte
AS (SELECT *
FROM TBL
WHERE TBL.Err_Type IN ( 4, 2 )
UNION
SELECT 4,
0
WHERE NOT EXISTS (SELECT 1
FROM TBL
WHERE TBL.Err_Type = 4)
UNION
SELECT 2,
0
WHERE NOT EXISTS (SELECT 1
FROM TBL
WHERE TBL.Err_Type = 2))
SELECT *
FROM cte