Show All Duplicate Records QUERY - sql

What is the query that will show all the records that have multiple names?
For example.
Table 1:
| ID | Name | Age | Email |
+----+---------+-------+-----------------+
| 1 | Mike | 12 | mike#gmail.com |
| 2 | Mon | 10 | mon#gmail.com |
| 3 | Peter | 12 | pet#gmail.com |
| 4 | Mike | 13 | mike12#gmail.com|
Desired result:
| ID | Name | Age | Email |
+----+---------+-------+-----------------+
| 1 | Mike | 12 | mike#gmail.com |
| 4 | Mike | 13 | mike12#gmail.com|

One option, using COUNT() as an analytic function:
WITH cte AS (
SELECT t.*, COUNT(*) OVER (PARTITION BY Name) cnt
FROM yourTable t
)
SELECT ID, Name, Age, Email
FROM cte
WHERE cnt > 1;

You can use GROUP BY and join result to origin table
SELECT t1.*
FROM myTable t1
JOIN
(SELECT Name
FROM myTable
GROUP BY Name
HAVING COUNT(Name) > 1) t2
ON t1.Name = t2.Name

Related

How to sum rows before a condition is met in SQL

I have a table which has multiple records for the same id. Looks like this, and the rows are sorted by sequence number.
+----+--------+----------+----------+
| id | result | duration | sequence |
+----+--------+----------+----------+
| 1 | 12 | 7254 | 1 |
+----+--------+----------+----------+
| 1 | 12 | 2333 | 2 |
+----+--------+----------+----------+
| 1 | 11 | 1000 | 3 |
+----+--------+----------+----------+
| 1 | 6 | 5 | 4 |
+----+--------+----------+----------+
| 1 | 3 | 20 | 5 |
+----+--------+----------+----------+
| 2 | 1 | 230 | 1 |
+----+--------+----------+----------+
| 2 | 9 | 10 | 2 |
+----+--------+----------+----------+
| 2 | 6 | 0 | 3 |
+----+--------+----------+----------+
| 2 | 1 | 5 | 4 |
+----+--------+----------+----------+
| 2 | 12 | 3 | 5 |
+----+--------+----------+----------+
E.g. for id=1, i would like to sum the duration for all the rows before and include result=6, which is 7254+2333+1000+5. Same for id =2, it would be 230+10+0. Anything after the row where result=6 will be left out.
My expected output:
+----+----------+
| id | duration |
+----+----------+
| 1 | 10592 |
+----+----------+
| 2 | 240 |
+----+----------+
The sequence has to be in ascending order.
I'm not sure how I can do this in sql.
Thank you in advance!
I think you want:
select t2.id, sum(t2.duration)
from t
where t.sequence <= (select t2.sequence
from t t2
where t2.id = t.id and t2.result = 6
);
In PrestoDB, I would recommend window functions:
select id, sum(duration)
from (select t.*,
min(case when result = 6 then sequence end) over (partition by id) as sequence_6
from t
) t
where sequence <= sequence_6;
You can use a simple aggregate query with a condition that uses a subquery to recover the sequence corresponding to the record whose sequence is 6 :
SELECT t.id, SUM(t.duration) total_duration
FROM mytable t
WHERE t.sequence <= (
SELECT sequence
FROM mytable
WHERE id = t.id AND result = 6
)
GROUP BY t.id
This demo on DB Fiddle with your test data returns :
| id | total_duration |
| --- | -------------- |
| 1 | 10592 |
| 2 | 240 |
Basic group by query should solve your issue
select
id,
sum(duration) duration
from t
group by id
for the certain rows:
select
id,
sum(duration) duration
from t
where id = 1
group by id
if you want to include it in your result set
select id, duration, sequence from t
union all
select
id,
sum(duration) duration
null sequence
from t
group by id

How to convert fields to rows in Sql

Suppose I have a table like this:
+------------+-----------+--+--+--+
| First name | Last name | | | |
+------------+-----------+--+--+--+
| First 1 | Last 1 | | | |
+------------+-----------+--+--+--+
| First 2 | Last 2 | | | |
+------------+-----------+--+--+--+
| First 3 | Last 3 | | | |
+------------+-----------+--+--+--+
How would I create a query that displays the data like this
+---------+--+--+--+--+
| Name | | | | |
+---------+--+--+--+--+
| First 1 | | | | |
+---------+--+--+--+--+
| Last 1 | | | | |
+---------+--+--+--+--+
| First 2 | | | | |
+---------+--+--+--+--+
| Last 2 | | | | |
+---------+--+--+--+--+
| First 3 | | | | |
+---------+--+--+--+--+
| Last 3 | | | | |
+---------+--+--+--+--+
with fnames as
(
select fname Name, ROW_NUMBER() over (order by fname,lname) rank from myTable
), lnames as
(
select lname Name, 0.5 + ROW_NUMBER() over (order by fname,lname) rank from myTable
),
merged as
(
(select * from fnames) union (select * from lnames)
)
select Name from merged order by rank
Assuming every other column is repeated, and there is no ID column initially
WITH T (FirstName, LastName,Ranking)
AS
(
SELECT
FirstName,
LastName,
2* ROW_NUMBER() OVER(ORDER First Name, Last Name) AS Ranking --, other columns
FROM TBL
)
SELECT Name --, other columns
FROM
(
SELECT FirstName AS Name,
Ranking-1 as r--, other columns
FROM T
UNION
SELECT LastName AS Name,
Ranking as r--, other columns
FROM T
) Tbl ORDER BY r ASC

combine two select query

I have two select query like
select name1,age1 from table1
output :
+--------+------+
| name1 | age1 |
+--------+------+
| ravi | 25 |
| rakhav | 12 |
| joil | 10 |
+--------+------+
select color,no from table2
output
+--------+----+
| color | no |
+--------+----+
| red | 3 |
| yellow | 4 |
+--------+----+
i want the output like
+--------+------+--------+----+
| name1 | age1 | color | no |
+--------+------+--------+----+
| ravi | 25 | red | 3 |
| rakhav | 12 | yellow | 4 |
| joil | 10 | | |
+--------+------+--------+----+
Try this:
select * from
(select name1, age1, row_number() over(order by age1 desc) as rn from table1) as t1
left join
(select color, no, row_number() over(order by no) as rn from table2) as t2
on t1.rn = t2.rn
try select t1.*, t2.* from table1 t1, table2 t2

Sql: Aggregation First() After Order by and Group by

id | name | value | time |
--------------------------
1 | A | 1 | 1 |
2 | B | 2 | 2 |
3 | C | 2 | 3 |
4 | A | 3 | 3 |
5 | A | 4 | 2 |
and I expected the result as below:
name | value |
--------------
A | 3 |
B | 2 |
C | 2 |
The results are to show name and value which are lastest time and not duplicate with name.
And I try to query:
SELECT name,First(value)
FROM
(SELECT name,value,time
FROM test
ORDER BY time DESC
)
GROUP BY name;
But I got this result:
name | value |
--------------
A | 1 |
B | 2 |
C | 2 |
I don't understand why A value isn't 3 because from subselect I got A values are 3,4,1 respectively.
Query:
SQLFIDDLEExample
SELECT t.name,
(SELECT t1.value
FROM test t1
WHERE t1.name = t.name
ORDER BY t1.time DESC
LIMIT 1) AS value
FROM test t
GROUP BY t.name
Result:
| NAME | VALUE |
----------------
| A | 3 |
| B | 2 |
| C | 2 |
also you can use partitionby
;with cte as (
select id, row_number() over (order by time desc) rn
from test
)
select * from test
join cte on test.id = cte.id and rn = 1
just choose the one which is faster

SQL Select top frequent records

I have the following table:
Table
+----+------+-------+
| ID | Name | Group |
+----+------+-------+
| 0 | a | 1 |
| 1 | a | 1 |
| 2 | a | 2 |
| 3 | a | 1 |
| 4 | b | 1 |
| 5 | b | 2 |
| 6 | b | 1 |
| 7 | c | 2 |
| 8 | c | 2 |
| 9 | c | 1 |
+----+------+-------+
I would like to select top 20 distinct names from a specific group ordered by most frequent name in that group. The result for this example for group 1 would return a b c (
a - 3 occurrences, b - 2 occurrences and c - 1 occurrence).
Thank you.
SELECT TOP(20) [Name], Count(*) FROM Table
WHERE [Group] = 1
GROUP BY [Name]
ORDER BY Count(*) DESC
SELECT Top(20)
name, group, count(*) as occurences
FROM yourtable
GROUP BY name, group
ORDER BY count(*) desc
SELECT
TOP 20
Name,
Group,
COUNT(1) Count,
FROM
MyTable
GROUP BY
Name,
Group
ORDER BY
Count DESC