SQL Join different item from one table - sql

I have a table
Tablename = table01
ID Item value
4 a 10
5 b 12
5 c 15
and my sql
select value as b from table01 where ID = 5 and Item = b
select value as c from table01 where ID = 5 and Item = c
How can i join this two sql?
this is my imagine result
b c
12 15

Here is one method:
select t1.id, t1.value as b, t2.value as c
from table1 t1 join
table1 t2
on t1.id = t2.id and t1.item = 'b' and t2.item = 'c';

SELECT MAX( CASE WHEN Item = 'b' THEN value END ) AS b,
MAX( CASE WHEN Item = 'c' THEN value END ) AS c
FROM table01;

Here is one way using Conditional Aggregate
select max(case when Item = 'b' then value end),
max(case when Item = 'c' then value end)
from yourtable
Where ID = 5
and Item in ( 'b' , 'c')
Note : This considers that ID & ITEM combination is not duplicated. If it is duplicated then you will max value out of duplicate

Related

Comparing a particular column value for two rows in SQL

I have a table as follows:
ID Version Type Value
121 1 A 100
121 1 B 200
122 2 A 300
122 2 B 300
123 3 A 300
123 3 B 300
124 4 A 420
124 4 B 420
121 3 A 410
121 3 B 410
I am trying to build a query which gives returns the rows where "Value" is different between Type A and Type B for same ID and Version.
For example, in the above scenario, ID and Version is Unique 5 times (121-1,122-2,123-3,124-4,121-3). I would look at "Type" for each unique group and compare "Value" for Type A and Type B.
The above scenario should return:
ID Version Type Value
121 1 A 100
121 1 B 200
The above two rows are the only ones with different "Value" for unique ID and Version and among Type A and Type B.
Any help will be greatly appreciated :)
You can use exixts :
select t.*
from table t
where exists (select 1
from table t1
where t1.id = t.id and
t1.Version = t.Version and
t1.type <> t.type and
t1.Value <> t.Value
);
You can join a table to itself:
SELECT *
FROM [MyTable] t0
INNER JOIN [MyTable] t1 ON t1.ID = t0.ID AND t0.Type <> t1.Type AND t0.Value <> t1.Value
or
SELECT *
FROM [MyTable] t0
INNER JOIN [MyTable] t1 ON t1.ID = t0.ID AND t1.Type = 'B' AND t0.Value <> t1.Value
WHERE t0.Type = 'A'
If you have only two types, I am going to recommend a different result set format:
select id, version,
max(case when type = 'A' then value end) as value_a,
max(case when type = 'B' then value end) as value_b
from t
where type in ('A', 'B')
group by id, version,
having max(case when type = 'A' then value end) <> max(case when type = 'B' then value end);
I recommend this because a typical follow-on question might be "how big is the difference".
This is one way to approach this problem:
select *
from t1
where (id, value, version) in (select id, value, version
from t1
group by id, value, version
having count(id) = 1);
Here is a DEMO
This is what I ended up doing:
SELECT MAX(Value), MIN(Value)
FROM table_name
GROUP BY ID, Version
HAVING MAX(Value)<>MIN(Value);

Find the 2nd row of data based on a column value, if not available then print NULL

I am working on some project in hive and below problem is one part of it. Please note that i am going to apply the solution for this query on a subquery result /table which i have already made.
So as part of this, i am trying to print the row for each id based on column value of rnum. If rnum=2 then print both the column values, i.e., id,value. If rnum= 2 is not present for an id then then print id,'No value'.
Give below sample input and expected output.
For eg.
for id 100, since rnum is only 1, hence print value as 'No value'
for id 200, print only value for rnum=2, i.e., xyz and ignore value for rnum=1,3 and 4
Input:
id value rnum
100 abc 1
200 def 1
200 xyz 2
200 rtz 3
200 tgv 4
Expected output:
id value
100 No Value
200 xyz
You can use aggregation and case logic:
select id,
(case when sum(case when mum = 2 then 1 else 0 end) > 0
then max(case when mum = 2 then value end)
else 'No Value'
end)
from t
group by id;
You can do it as shown below:
select a.id, case when t.id is null then 'No value' else t.value end
from (select distinct id as id from t) a
left join t on t.rnum = 2 and a.id = t.id
Here's your query.
select t1.id, case when t2.rnum != 1 then t2.value else 'no value' end
from (
select count(1) as ct, id from test2
group by id) t1
left join test2 t2 on t2.id = t1.id and t2.rnum = 2
order by t1.id asc
Changed, allowing for any id values:
with t2(id, cnt) as
(
select id, count(*) as cnt
from t1
group by id
)
select t1.id,
max(case
when t2.cnt = 1 and t1.rnum = 1 then 'No Value'
when t2.cnt > 1 and t1.rnum = 2 then value
end)
from t1
join t2 on t2.id = t1.id
group by t1.id

Merge multiple columns into one column with multiple rows

In PostgreSQL, how can I merge multiple columns into one column with multiple rows?
The columns are all boolean, so I want to:
Filter for true values only
Replace the true value (1) with the name of the column (A, B or C)
I have this table:
ID | A | B | C
1 0 1 0
2 1 1 0
3 0 0 1
4 1 0 1
5 1 0 0
6 0 1 1
I want to get this table:
ID | Letter
1 B
2 A
2 B
3 C
4 A
4 C
5 A
6 B
6 C
I think you need something like this:
SELECT ID, 'A' as Letter FROM table WHERE A=1
UNION ALL
SELECT ID, 'B' as Letter FROM table WHERE B=1
UNION ALL
SELECT ID, 'C'as Letter FROM table WHERE C=1
ORDER BY ID, Letter
SELECT ID,
(CASE
WHEN TABLE.A = 1 then 'A'
WHEN TABLE.B = 1 then 'B'
WHEN TABLE.C = 1 then 'C'
ELSE NULL END) AS LETTER
from TABLE
You may try this.
insert into t2 select id, 'A' from t1 where A=1;
insert into t2 select id, 'B' from t2 where B=1;
insert into t2 select id, 'C' from t3 where C=1;
If you care about the order, then you can do this.
insert into t3 select id, letter from t2 order by id, letter;
W/o UNION
You can use a single query to get the desired output.Real time example
select id
,regexp_split_to_table((
concat_ws(',', case
when a = 0
then null
else 'a'
end, case
when b = 0
then null
else 'b'
end, case
when c = 0
then null
else 'c'
end)
), ',') l
from c1;
regexp_split_to_table() & concat_ws()

Union three tables and show where data came from

have no idea how to solve following:
There are three tables each with a column of names, for example
Table 1 - column name 'Name' - values 'A', 'B' and 'C'
Table 2 - column name 'Name' - values 'A' and 'B'
Table 3 - column nane 'Name' - values 'A' and 'C'
The goal is to UNION the tables - each value of the three tables should be shown only one time. In addition there should be three new "virtual columns" showing in which table the value is included('1' when value is included, '0' if not). So the result should look like this:
Value | Table1 | Table2 | Table3
--------------------------------
A | 1 | 1 | 1
B | 1 | 1 | 0
C | 1 | 0 | 1
Hope someone can help me, thanks in advance.
Does this do what you want?
select Name, max(Table1) as Table1, max(Table2) as Table2, max(Table3) as Table3
from (select Name, 1 as Table1, 0 as Table2, 0 as Table3
from table1
union all
select Name, 0 as Table1, 1 as Table2, 0 as Table3
from table2
union all
select Name, 0 as Table1, 0 as Table2, 1 as Table3
from table3
) t
group by Name;
You might want to use sum() instead of max() to get the number of times the value occurs in each table.
If your db supports full joins you can try the query below.
select
coalesce(t1.Name,t2.Name,t3.Name) myValue,
(case when max(t1.Name) is not null then 1 else 0 end) c1,
(case when max(t2.Name) is not null then 1 else 0 end) c2,
(case when max(t3.Name) is not null then 1 else 0 end) c3
from
Table1 t1
full join Table2 t2 on t1.Name = t2.Name
full join Table3 t3 on t1.Name = t3.Name
group by coalesce(t1.Name,t2.Name,t3.Name)
If you know that a value will not appear more than once in each table, you can remove the group by and max parts.
Here's my attempt (update: works f.e. in SQL-Server 2005 and upwards due to the CTE):
With names AS
(
SELECT Name, Source = 'T1'
FROM dbo.Table1
UNION ALL
SELECT Name, Source = 'T2'
FROM dbo.Table2
UNION ALL
SELECT Name, Source = 'T3'
FROM dbo.Table3
)
SELECT n.Name,
Table1 = CASE WHEN EXISTS
(SELECT 1 FROM names n2
WHERE Source = 'T1' AND n2.Name=n.Name)
THEN 1 ELSE 0 END,
Table2 = CASE WHEN EXISTS
(SELECT 1 FROM names n2
WHERE Source = 'T2' AND n2.Name=n.Name)
THEN 1 ELSE 0 END,
Table3 = CASE WHEN EXISTS
(SELECT 1 FROM names n2
WHERE Source = 'T3' AND n2.Name=n.Name)
THEN 1 ELSE 0 END
FROM names n
GROUP BY n.Name
Demo

To retrieve records having only two specific values

Have the following Data in the table
Example Table
ID Value
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
I need to retrieve records having ID with only two values a and b.
So i am expecting only the Record with ID 3 .
Can anyone help me with the query
I guess you could do something like
select
ID,
sum(case when value = 'a' then 1
when value = 'b' then 1
else 3 end)
from
table1
group by id
having
sum (case when value = 'a' then 1
when value = 'b' then 1
else 3 end) =2
SQL Fiddle
That will work:
select x.id from
(
select id from mytable where value = 'a'
union all
select id from mytable where value = 'b'
) x
group by x.id
having COUNT(*) = 2
and not exists (select * from mytable t where t.id = x.id and value <> 'a' and value <> 'b')