The table is as follows:
id name
1 tom
2 bob
3 tom
4 tom
5 harry
I'm looking for a query that would result in the following:
id name duplicateposition
1 tom 1
2 bob 1
3 tom 2
4 tom 3
5 harry 1
So duplicateposition for the first tom is 1, for the second tom is 2, and for the third tom is 3. The first bob is 1 and the first harry is 1. Is there an easy query to do this?
Here is my attempt:
SELECT id, name, count(id) from table
I'm a little new to sql so that is my best shot.
You can do the following. It partitions the data by name and assigns a number within the partition. Forgot to mention I did this in SQL Server 2012.
select *,
row_number() over (partition by name order by id) as DuplicatePosition
from test
order by id
SQL Fiddle Demo
Here's a generic self join that works on most databases (although if you have access to window functions you should use them instead as they're generally faster)
select t1.id, t1.name, count(t2.id) duplicateposition
from mytable t1
join mytable t2
on t2.name = t1.name
and t2.id <= t1.id
group by t1.id, t1.name
order by t1.id
Related
Say I have the following three tables:
Table 1
ID NAME
1 John
Table 2
ID ITEM
1 apple
2 orange
3 banana
Table 3
ID NAME ITEM
1 Mike mango
2 Mike grape
What is the most efficient way using SQL to merge Tables 1 and 2 together and append the result to Table 3 in order to get the following result (but leave 1 and 2 as they are)?
Table 3 after operation
ID NAME ITEM
1 Mike mango
2 Mike grape
3 John apple
4 John orange
5 John banana
Just insert a cross join between the 2.
But don't insert those that already exist in table 3.
insert into "Table 3" (name, item)
select t1.name, t2.item
from "Table 1" as t1
cross join "Table 2" as t2
where not exists (
select 1
from "Table 3" t3
where t3.name = t1.name
and t3.item = t2.item
);
You can use cross join with union all:
select row_number() over (order by t.name, t.item) id, t.* from (
select t2.name, t2.item from table2 t2
union all
select t1.name, t3.item from table1 t1 cross join table3 t3) t
I have two tables like below. I am using SQL DB.
Table1:
Id Name
1 leo
2 lin
3 kim
4 ken
5 jon
6 kelly
Table2:
Id Name Date
1 leo 2019-04-11
2 lin 2019-04-17
3 kim 2019-02-15
4 ken 2018-04-11
I am trying to compare this two table and find out which name in table1 does not have a Date.
I need this output.
Result:
Id Name
5 jon
6 kelly
Could anyone please help me with this query.
Use a LEFT JOIN:
SELECT * FROM Table1
LEFT JOIN Table2
ON Table1.Name = Table2.Name
WHERE Table2.Name is NULL
Or you can use WHERE NOT EXISTS:
SELECT * From Table1
WHERE NOT EXISTS (SELECT 1 FROM Table2 WHERE Table1.Name = Table2.Name)
Or you can use WHERE NOT IN:
SELECT * From Table1
WHERE Name NOT IN (SELECT Name FROM Table2)
Try this below:
SELECT Id,Name FROM Table1
EXCEPT
SELECT Id,Name FROM Table2
I've a table with users by structure like this:
id name parent_id
1 Mike
2 Jack 1
3 Sam 1
4 Kurt 1
5 Somebody 3
6 Tommy 4
6 etc.. 2
How to get a max count of referral on first level nesting per user, by this example I expect result:
3 because Jack, Sam, Kurt is a referral of Mike on first level
Assuming "first level" is defined by parent_id IS NULL and the current version Postgres 9.4:
SELECT parent_id, count(*) AS referral_ct
FROM (
SELECT id AS parent_id
FROM tbl
WHERE t1.parent_id IS NULL
) t1
JOIN tbl t2 USING (parent_id)
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1; -- to only get 1 row with max. referral_ct
With only few root nodes, JOIN LATERAL may be faster:
SELECT t1.id, t2.referral_ct
FROM (
SELECT id
FROM tbl
WHERE parent_id IS NULL
) t1
LEFT JOIN LATERAL (
SELECT parent_id, count(*) AS referral_ct
FROM tbl
WHERE parent_id = t1.id
GROUP BY 1
) t2 ON true
ORDER BY 2 DESC
LIMIT 1; -- to only get 1 row with max. referral_ct
Related, with more explanation:
Optimize GROUP BY query to retrieve latest record per user
I have two tables:
Table1
id name qty
1 Tedd 6
2 Jim 7
3 Sally 8
4 Victoria 1
Table2
id name qty
1 Tedd 2
2 Jim 2
3 Sally 2
4 Victoria 1
5 Alex 9
I need to select all the rows from Table1. However, if a row exists in Table2 that doesn't exist in Table1, I need to include that in the result set. So, in the end, my query should return this:
id name qty
1 Tedd 6
2 Jim 7
3 Sally 8
4 Victoria 1
5 Alex 9
Is there a way I can do this? Thanks.
You can use a FULL OUTER JOIN:
select
coalesce(t1.id, t2.id) id,
coalesce(t1.name, t2.name) name,
coalesce(t1.qty, t2.id) qty
from table1 t1
full outer join table2 t2
on t1.id = t2.id
See SQL Fiddle with Demo
If I have data like this:
Key
Name
1
Dan
2
Tom
3
Jon
4
Tom
5
Sam
6
Dan
What is the SQL query to bring back the records where Name is repeated 2 or more times?
So the result I would want is
Tom
Dan
Couldn't be simpler...
Select Name, Count(Name) As Count
From Table
Group By Name
Having Count(Name) > 1
Order By Count(Name) Desc
This could also be extended to delete duplicates:
Delete From Table
Where Key In (
Select Max(Key)
From Table
Group By Name
Having Count(Name) > 1
)
select name from table group by name having count(name) > 1
This could also be accomplished by joining the table with itself,
SELECT DISTINCT t1.name
FROM tbl t1
INNER JOIN tbl t2
ON t1.name = t2.name
WHERE t1.key != t2.key;