Oracle SQL query joining same table - sql

I have a table like this:
items
id old_new object
1 o pen
2 n house
3 o dog
4 o cat
5 n carrot
I would like the select return:
id new_object old_object
1 null pen
2 house null
3 null dog
4 null cat
5 carrot null
Do I need to use an outer join on the same table?

No join needed:
select id,
case when old_new = 'n' then object end as new_object,
case when old_new = 'o' then object end as old_object
from the_table
order by id;

Related

SQL - Deleting duplicate rows without leaving original

How to delete duplicate rows based on select columns without leaving original? In this example, deleting based on Name and Animal.
ID Name Animal Fruit
1 Bob Dog Orange
2 Adam Dog Orange
3 Bob Dog Apple
4 Adam Cat Orange
5 Bob Cat Apple
6 Bob Hamster Apple
7 Adam Cat Apple
So the expected result would be:
ID Name Animal Fruit
2 Adam Dog Orange
5 Bob Cat Apple
6 Bob Hamster Apple
You can use a delete with join the subquery grouped by name and animal having count > 1
delete m
from my_table m
inner join (
select name, animal
from my_table
group by name, animal
having count(*) > 1
) t on t.name = m.name
and t.animal = m.animal
try this:
first, select the duplicates in a subquery.
then, delete all results
delete from mytable T
left join
(select count(*) cnt, Name, Animal
from mytable
group by Name, Animal) X
on t.Name = X.Name
and t.Animal = X.Animal
where cnt>1
I would do this using exists:
delete from t
where exists (select 1
from t t2
where t2.name = t.name and t2.animal = t.animal and t2.id <> t.id
);

Attributed null values to each ID in Athena (Presto)

Here is what my initial dataset looks like
prof_id id title
1 5 A
1 5 B
1 5 C
1 5 D
2 5 C
2 5 D
2 5 E
NA 5 F
NA 5 G
Here is what the new table should look like:
prof_id id title
1 5 A
1 5 B
1 5 C
1 5 D
1 5 F
1 5 G
2 5 C
2 5 D
2 5 E
2 5 F
2 5 G
Any row with a null value for a prof_id should be attributed to all of the prof_id. I have provided an example where there are two '
prof_id but there are also instances where there are 1 or 0 prof_id.
For 1, all of the null should be attributed to that single prof_id
For 0, leave it as is
I'm new to SQL so I'm not sure how to start. Any guidance would be much appreciated.
Thanks
In this case, you will need to do cross join, where essentially it is going to multiply 2 tables together.
First to pick out all nulls:
select id, title from table where prof_id is null
Then pick out the prof_id you want to apply to all tables
select distinct prof_id from table where prof_is is not null
Do a cross join together, then union the rest of "good" data back
(select distinct prof_id from table where prof_is is not null)
CROSS JOIN
(select id, title from table where prof_id is null)
UNION ALL
(select prof_id, id, title from table where prof_id is not null)
You can generate all the rows using a cross join. Then use union all to combine this with the rest of the data.
The following syntax should work:
select p.prof_id, i.id, t.title
from (select distinct prof_id
from t
where prof_id <> 'NA' -- or do you mean is not null
) p cross join
(select distinct id from t) i cross join
(select distinct title
from t
where prof_id = 'NA' -- or is null
) t
union all
select prof_id, id, title
from t
where prof_id <> 'NA' -- or is not null

Query to get translation for each languages

Please help me to create query. I have table with languages like
Id Code
---------
1 EN
2 DE
3 RU
and table with translations
Id Code LanguageId Value
------------------------------------------
1 1 1 EnglishTranslation
2 1 3 RussianTranslation
3 2 1 EnglishTranslation
4 2 2 DeutschTranslation
5 3 1 EnglishTranslation
I'm trying to get this result
Id Code LanguageId Value
------------------------------------------
1 1 1 EnglishTranslation
1 1 2 NULL
2 1 3 RussianTranslation
3 2 1 EnglishTranslation
4 2 2 DeutschTranslation
4 2 3 NULL
5 3 1 EnglishTranslation
5 3 2 NULL
5 3 3 NULL
Need to get translations for all languages by Code from Translations table So far I try
select
T.id, T.Code, L.Id, T.Value
from Languages L
left join Translations T on T.LanguageId = L.Id
but I got not expected result. Could you please suggest
http://sqlfiddle.com/#!6/e9bed/1
You can use CROSS JOIN operator to construct a cartesian product of (LanguageId, Code) pairs, and left-join translation table to it:
SELECT
t.Id, y.Code, x.LanguageId, t.Value
FROM
((SELECT Id AS LanguageId FROM Languages) AS x
CROSS JOIN
(SELECT DISTINCT(Code) AS Code FROM Translations) AS y)
LEFT OUTER JOIN Translations t ON y.Code=t.Code AND x.LanguageId=t.LanguageId
ORDER BY t.Code, t.LanguageId
Note that this wouldn't produce a valid translation Id for rows missing from Translations, i.e. the result would look like this:
Id Code LanguageId Value
---------------------------------------------
1 1 1 EnglishTranslation
NULL 1 2 NULL
2 1 3 RussianTranslation
3 2 1 EnglishTranslation
4 2 2 DeutschTranslation
NULL 2 3 NULL
5 3 1 EnglishTranslation
NULL 3 2 NULL
NULL 3 3 NULL
Demo.
I resolved the issue and got the result that you expected.
Run the below query:
SELECT
(CASE
WHEN T.Id is null and lc.Code = 1 THEN 1
WHEN T.Id is null and lc.Code = 2 THEN 4
WHEN T.Id is null and lc.Code = 3 THEN 5
ELSE T.Id
END) as Id,
lc.Code, lc.Id as LanguageId, T.Value from
(SELECT x.Id, y.Code from (SELECT Id FROM Languages) x cross join (SELECT DISTINCT(Code) as Code FROM Translations) y) as lc
left outer join Translations T ON lc.Id = T.LanguageId and lc.Code = T.Code
order by Id, Code, LanguageId
You can also see the solution in the below link:
http://sqlfiddle.com/#!6/e9bed/30
Hopefully it will work as you like.

Select all categories with COUNT of sub-categories

I need to select all categories with count of its sub-categories.
Assume here are my tables:
categories
id | title
----------
1 | colors
2 | animals
3 | plants
sub_categories
id | category_id | title | confirmed
------------------------------------
1 1 red 1
2 1 blue 1
3 1 pink 1
4 2 cat 1
5 2 tiger 0
6 2 lion 0
What I want is :
id | title | count
------------------
1 colors 3
2 animals 1
3 plants 0
What I have tried so far:
SELECT c.id, c.title, count(s.category_id) as count from categories c
LEFT JOIN sub_categories s on c.id = s.category_id
WHERE c.confirmed = 't' AND s.confirmed='t'
GROUP BY c.id, c.title
ORDER BY count DESC
The only problem with this query is that this query does not show categories with 0 sub categories!
You also can check that on SqlFiddle
Any help would be great appreciated.
The reason you don't get rows with zero counts is that WHERE clause checks s.confirmed to be t, thus eliminating rows with NULLs from the outer join result.
Move s.confirmed check into join expression to fix this problem:
SELECT c.id, c.title, count(s.category_id) as count from categories c
LEFT JOIN sub_categories s on c.id = s.category_id AND s.confirmed='t'
WHERE c.confirmed = 't'
GROUP BY c.id, c.title
ORDER BY count DESC
Adding Sql Fiddle: http://sqlfiddle.com/#!17/83add/13
I think you can try this too (it evidence what column(s) you are really grouping by):
SELECT c.id, c.title, RC
from categories c
LEFT JOIN (SELECT category_id, COUNT(*) AS RC
FROM sub_categories
WHERE confirmed= 't'
GROUP BY category_id) s on c.id = s.category_id
WHERE c.confirmed = 't'
ORDER BY RC DESC

T-SQL recursive query - how to do it?

I have a table with self referencing relation,
ID parentID UserId Title
1 null 100 A
2 1 100 B
3 2 100 C
4 2 100 D
5 null 100 E
6 5 100 F
I want to update UserId from 100 to 101 for all records with ID=1 and its children, so I want to have
ID parentID UserId Title
1 null 101 A
2 1 101 B
3 2 101 C
4 2 101 D
5 null 100 E
6 5 100 F
How can I do it in T-SQL?
You probably want to use a common table expression which allows you to generate recursive queries.
eg:
;with cte as
(
select * from yourtable where id=1
union all
select t.* from cte
inner join yourtable t on cte.id = t.parentid
)
update yourtable
set userid = 101
where id in (select id from cte)