How to fetch duplicate rows from the same table - duplicates

Assuming I have a table like:
ID
valA
valB
valC
1
21
aaaaa
NYC
4
12
bbbbb
NYC
2
31
ddddd
LA
2
23
eeeee
LA
2
41
fffff
NE
3
23
ggggg
JE
3
44
hhhhh
KA
I want to compare rows to find those with certain data matching. In this case I want to identify rows with matching ID and valC. The contents of the valA and valB column are ignored.
So, it should find only those two rows:
ID
valA
valB
valC
2
31
ddddd
LA
2
23
eeeee
LA
I tried something with "count()" and "inner Join" but I didnt get the result what I am expecting.
I am pretty new on SQL so I would appreciate any tipps and suggestions.

One approach, using analytic functions:
WITH cte AS (
SELECT t.*, COUNT(*) OVER (PARTITION BY ID, valC) cnt
FROM yourTable t
)
SELECT ID, valA, valB, valC
FROM cte
WHERE cnt > 1;

Alternate approach by filtering concatenated id, valc that are stored more than once:
SELECT
*
FROM table_name
WHERE id||valc in
(SELECT
id||valc
FROM
TABLE_NAME
GROUP BY (id_, valc)
HAVING count(1) > 1);

Related

select rows in mysql with latest date for each quiz_id repeated multiple times

I have a table where each quiz ID is repeated multiple times. there is a date in front of each quiz id in each row. I want to select entire row for each quiz ID where date is latest with user. The date format is mm/dd/YYYY.
Sample -
USER_ID Quiz_id Name Date Marks .. .. ..
1 2 poly 4/3/2020 27
1 2 poly 4/3/2019 98
1 4 moro 4/3/2020 09
2 5 cat 4/12/2015 87
2 4 moro 4/3/2009 56
2 6 PP 4/3/2011 76
3 2 poly 4/3/2020 12
3 2 poly 5/3/2020 09
3 7 dog 4/3/2011 23
I want result look like this:Result
USER_ID Quiz_id Name Date Marks .. .. ..
1 2 poly 4/3/2020 27
1 4 moro 4/3/2020 09
2 5 cat 4/12/2015 87
2 4 moro 4/3/2009 56
2 6 PP 4/3/2011 76
3 2 poly 5/3/2020 09
3 7 dog 4/3/2011 23
You can use rank function to get the desired result:
Demo
SELECT A.* FROM (
SELECT A.*, RANK() OVER(PARTITION BY USER_ID,QUIZ_ID, NAME ORDER BY DATE DESC) RN FROM
Table1 A ORDER BY USER_ID) A WHERE RN = 1 ORDER BY USER_ID, QUIZ_ID;
I don't have MySQL installed so you will need to test and report back. The general idea is to identify the row of interest using max and a group by (table t). As the Date column appears to be text column (MySQL uses the format YYYY-MM-DD for dates) you will need to convert it to a date with str_to_date() so you can use the max() aggregate function. Finally, join with the original table (here table t2 to do the date conversion), as only the aggregate column(s) and columns named in the group by are well defined (in table t1), i.e.:
select USER_ID, Quiz_id, Date, Marks from (
select USER_ID, Quiz_id, max(str_to_date(Date, '%m/%d/%Y')) as Date2 from quiz group by 1, 2
) as t natural join (
select *, str_to_date(Date, '%m/%d/%Y') Date2 from Quiz
) as t2;
I don't recall off-hand but Date might be reserved word, in which case you will need to quote the column name, or ideally rename said column to use a better name.
Also, the original table is not in 3rd normal form as Quiz_id depends on Name. Quiz_id, as implied, should be a foreign key to a lookup table that holds the Name.

Mysql - Order rows that have same columns content

have a Mysql table like that
id primary key ( idstudy, idarea and idcategory are foreign keys )
**** Table : Operations
id idstudy idarea idcategory content lang
1 22 11 3 content1EN EN
2 22 11 3 content1FR FR
3 22 11 3 Content2FR FR
4 22 11 3 Content2EN EN
5 35 10 5 Content5EN EN
6 35 10 5 Content5FR FR
7 35 23 12 Content5EN EN
8 35 23 12 Content5FR FR
My goal : to assemble language to same row ( FR and EN) to get one row with one column in plus ( ContentEN for example) and remove lang column.
but my problème my table is not in order, and i cant reconnize by id, all i know are idstudy idarea and idcategory but those both are not unique , and sometimes i have 3 rows that are same except (id and content)
I have solution but i dont know how to write it in mysql : is to find all records with ( same idstudy same idarea same idcategory ) in one language then order them by adding column with ( 1 for first result, 2 for the second ...)
**** Table : Operations after order of groups ( idstudy, idarea, idcategory) in each language with new column ( order)
id idstudy idarea idcategory content lang order
1 22 11 3 content1EN EN 1
2 22 11 3 content1FR FR 1
3 22 11 3 Content2FR FR 2
4 22 11 3 Content2EN EN 1
5 35 10 5 Content5EN EN 1
6 35 10 5 Content5FR FR 1
7 35 23 12 Content5EN EN 1
8 35 23 12 Content5FR FR 1
I just need this result , after to assemble iwill do it using nodejs
note: sorry if my explanation is not so good.
Try this:
SELECT id, idstudy, idarea, idcategory, content, lang, dense_rank as 'order'
FROM (
SELECT
#dense:=IF(#prev_col1=t.idstudy AND #prev_col2=t.idarea AND #prev_col3=t.idcategory AND #prev_col4=t.lang, IF(#prev_col5=t.content, #dense, #dense+1), 1) AS dense_rank,
t.*,
#prev_col1:=t.idstudy, #prev_col2:=t.idarea, #prev_col3:=t.idcategory, #prev_col4:=t.lang, #prev_col5:=t.content
FROM (SELECT * FROM t1 ORDER BY idstudy, idarea, idcategory, lang, content ) t,
(SELECT #dense:=1, #prev_col1:=NULL, #prev_col2:=NULL, #prev_col3:=NULL, #prev_col4:=NULL, #prev_col5:=NULL) var
) F
ORDER BY idstudy, idarea, idcategory, lang, content;
In MySql you can mimic ms-sql analytics functions in this way Analytical Function in MySQL - ROW_NUMBER, RANK, DENSE_RANK
In SQL-Sever you could use DENSE_RANK()
SELECT *, DENSE_RANK() OVER (PARTITION BY idstudy, idarea, idcategory, lang ORDER BY content) [order]
FROM tableName
Fianllay i found another solution , i made two tables with same structure ( french and english), regenerate id of eeach table ( to be 1.2.3.for each).
As i have 500 rows in each table i checked each row if its Ok ( each id must concern same content in two languages )
Special thanks to #MtwStark for his time :) i appreciate your help
Sometimes when we try to explain our problem we find the solution :)

Combine query for sum of two tables with date

I have two tables like following
challenge_table
Challenger chdate
----------------------
abc 11-02-2012
aaa 12-02-2012
ccc 12-02-2012
bbb 13-02-2012
ddd 14-02-2012
init_table
Initiateid indate
----------------------
a1 11-02-2012
a2 11-02-2012
a3 12-02-2012
a4 13-02-2012
a5 13-02-2012
I need a result like this
challengecount initcount curdate
-----------------------------------
1 2 11-02-2012
2 1 12-02-2012
1 2 13-02-2012
1 0 14-02-2012
i tried a query like this
SELECT COUNT(*) challengecount, chdate caldate FROM challenge_table
UNION ALL
SELECT COUNT(*) Initiatecount, indate caldate FROM init_table
But it doesn't work for me.
Since MySQL does not support a FULL OUTER JOIN, you need to combine the 2 tables with a UNION.
Then group by the date and count the values of the 2 tables
select caldate, count(distinct Challenger), count(distinct Initiateid)
from
(
SELECT Challenger, null as Initiateid, chdate as caldate FROM challenge_table
UNION ALL
SELECT null, Initiateid, indate FROM init_table
) tmp
group by caldate

How to get count greater than and less than average values group by name

I have a data set with name and their transaction ,how to get average and count of transactions grater than that average and less than that average..
Name Transaction
John 12
John 34
John 45
John 66
John 32
chris 26
chris 54
chris 56
chris 99
chris 13
chris 4
kim 22
kim 34
kim 7
kim 11
kim 34
O/P will be
Name Avg Count_greater_than_Avg Count_Less_than_Avg
John 37.8 2 3
chris 42 3 3
kim 21.6 3 2
Thanks in advance..
Try this:
SELECT t1.Name, t2.Aver,
COUNT(CASE WHEN Transaction < Aver THEN 1 END) Count_Less_than_Avg,
COUNT(CASE WHEN Transaction > Aver THEN 1 END) Count_greater_than_Avg
FROM mytable AS t1
JOIN (
SELECT Name, AVG(Transaction * 1.0) AS Aver
FROM mytable
GROUP BY Name
) AS t2 ON t1.Name = t2.Name
GROUP By Name
You need a derived table in order to calculate the average value per Name. You can then JOIN the original table to this derived table and use conditional aggregation in order to calculate less than, greater than number of transactions.
Demo here
This basically first add a column Your_Avg using a correlated query, and then wrap it with another select to select the count of the occurrences of times smaller then avg and times larger.
SELECT tt.name,tt.Your_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Greater_Then_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Smaller_Then_Avg
FROM(
SELECT t.name,
(SELECT avg(s.transaction) FROM YourTable s WHERE s.name = t.name) as Your_Avg,
t.transaction
FROM YourTable) tt
GROUP BY tt.name

Finding the lone occurence of a value in a table

Lets say I have the following tables.
TABLE L
id name
51 joe
52 sara
53 john
54 david
TABLE M
id l_id
1 51
2 51
3 52
4 53
In table M, there are rows with multiple values for the information in table L. What I am trying to do is select a count of everything which appears just once in table m.
So in the above case, the count would be 2 because they are the l.id's that appear only once in table m:
COUNT(*)
2
How would I go about doing this?
select Count(*)
from
(select l_id From M group by l_id having count(*)=1) m
If you use a count(*) on a sub query which returns just the rows having a count of =1. My mysql is a little bit rusty but I hope the following code will give you an idea.
select count(*) from (
select l_id, count(*) count from m
group by l_id
having count(*) = 1
)
SELECT count(*)
FROM table
HAVING count(id) = 1;