How to display all duplicate value - mysql

Is there anyway I could display all the duplicate values in mysql using group by and having
+---------+--------------+------------+--------+----------+----------+---------+
| ENumber | EmpName | Birthdate | Gender | Address | Salary | DNumber |
+---------+--------------+------------+--------+----------+----------+---------+
| E001 | GSInocencio | 1988-01-15 | F | Munoz | 18000.00 | D005 |
| E002 | EAVillanueva | 1988-04-20 | F | Munoz | 23000.00 | D003 |
| E003 | ALedesma | 1988-05-25 | M | CLSU | 21000.00 | D002 |
| E004 | APGamilla | 1991-10-15 | F | Maligaya | 25000.00 | D001 |
| E005 | ACTolentino | 1989-02-20 | F | Maligaya | 30000.00 | D002 |
| E006 | ANVillasoto | 1999-01-05 | M | CLSU | 15000.00 | D004 |
| E007 | JPPalada | 1997-01-10 | M | Munoz | 21000.00 | D001 |
| E008 | NTNicodemus | 1995-04-15 | F | Maligaya | 22000.00 | D003 |
+---------+--------------+------------+--------+----------+----------+---------+
I want to display all the duplicate value in DNumber
+---------+--------------+------------+--------+----------+----------+---------+
| ENumber | EmpName | Birthdate | Gender | Address | Salary | DNumber |
+---------+--------------+------------+--------+----------+----------+---------+
| E004 | APGamilla | 1991-10-15 | F | Maligaya | 25000.00 | D001 |
| E007 | JPPalada | 1997-01-10 | M | Munoz | 21000.00 | D001 |
| E003 | ALedesma | 1988-05-25 | M | CLSU | 21000.00 | D002 |
| E005 | ACTolentino | 1989-02-20 | F | Maligaya | 30000.00 | D002 |
| E002 | EAVillanueva | 1988-04-20 | F | Munoz | 23000.00 | D003 |
| E008 | NTNicodemus | 1995-04-15 | F | Maligaya | 22000.00 | D003 |

display all the duplicate values in mysql using group by and having
There is more than one way to do it, but if you want to use group by and having, then you can join the table with an aggregate subquery that identifies the duplicates, as follows:
select t.*
from mytable t
inner join (
select dnumber
from mytable
group by dnumber
having count(*) > 1
) x on x.dnumber = t.dnumber
order by t.dnumber, t.enumber

Related

MySQL - calculate percent of a column with multiple column grouping

I have a table
desc test;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int(100) | YES | | NULL | |
| name | varchar(100) | YES | | NULL | |
| dept | varchar(10) | YES | | NULL | |
| sub | varchar(10) | YES | | NULL | |
| salary | int(100) | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
select * from test;
+------+-----------+------+------+--------+
| id | name | dept | sub | salary |
+------+-----------+------+------+--------+
| 1 | Rishabh | A | X | 150 |
| 2 | Manish | B | Y | 120 |
| 3 | Sachin | A | Z | 160 |
| 4 | Abhiskhek | C | Z | 100 |
| 5 | Manan | B | Z | 170 |
| 6 | Rahul | C | X | 150 |
| 7 | Rohan | C | Y | 120 |
| 8 | Mukul | B | Z | 110 |
| 9 | Lalit | B | X | 130 |
+------+-----------+------+------+--------+
So far I am able to do percent of a single column group
select dept, sum(salary), round(sum(salary)*100/t.s,2) as `perc`
from test cross join (select sum(salary) as s from test) t group by dept;
which yields the following:
+------+-------------+-------+
| dept | sum(salary) | perc |
+------+-------------+-------+
| A | 310 | 25.62 |
| B | 530 | 43.80 |
| C | 370 | 30.58 |
+------+-------------+-------+
so now I have another column to group by, I made the query,
select dept, sub, sum(salary), round(sum(salary)*100/t.s) as `perc`
from test cross join (select sum(salary) as s from test) t group by dept,sub;
which output the following:
+------+------+-------------+-------+
| dept | sub | sum(salary) | perc |
+------+------+-------------+-------+
| A | X | 150 | 12.40 |
| A | Z | 160 | 13.22 |
| B | X | 130 | 10.74 |
| B | Y | 120 | 9.92 |
| B | Z | 280 | 23.14 |
| C | X | 150 | 12.40 |
| C | Y | 120 | 9.92 |
| C | Z | 100 | 8.26 |
+------+------+-------------+-------+
it is making the relevant row percentage from the total sum = select sum(salary) from test;
but I expect it to show percent from it's respective group only, (in this case percent of sub's salary from total dept salary)
Expected output:
+------+------+-------------+-------+
| dept | sub | sum(salary) | perc |
+------+------+-------------+-------+
| A | X | 150 | 48.39 |
| A | Z | 160 | 51.61 |
| B | X | 130 | 24.53 |
| B | Y | 120 | 22.64 |
| B | Z | 280 | 52.83 |
| C | X | 150 | 40.54 |
| C | Y | 120 | 32.43 |
| C | Z | 100 | 27.03 |
+------+------+-------------+-------+
[yes I calculated these manually]
Kindly help me with correcting my query.

How can I enhance this query to use only one view?

I am learning SQL and DB, I need to make the following query, I need to make a query that finds the dates that there were more car crashes and list the names of the people who were involved in these car crashes
person
| name | id_person |
|--------|------------|
| Oliver | 000000001 |
| Harry | 000000002 |
| Jacob | 000000003 |
| Maria | 000000004 |
| Jack | 000000005 |
participated
| id_person | num_crash | cost_damage |
|------------|-------------|---------------|
| 00000001 | 11111101 | 200 |
| 00000002 | 11111102 | 120 |
| 00000003 | 11111102 | 120 |
| 00000004 | 11111103 | 400 |
| 00000005 | 11111104 | 300 |
| 00000002 | 11111105 | 280 |
| 00000005 | 11111106 | 260 |
crash
| num_crash | date_crash | crash_scene |
|-------------|--------------|-------------|
| 11111101 | 2020/04/28 | bairro 4 |
| 11111102 | 2020/05/01 | bairro 1 |
| 11111103 | 2020/05/01 | bairro 2 |
| 11111104 | 2020/05/04 | bairro 3 |
| 11111105 | 2020/05/04 | bairro 1 |
| 11111106 | 2020/05/04 | bairro 3 |
output example
| data_crash | num_crash | name |
|--------------|-------------|-------|
| 2020/05/04 | 11111104 | Jack |
| 2020/05/04 | 11111105 | Harry |
| 2020/05/04 | 11111106 | Jack |
| 2020/05/01 | 11111102 | Harry |
| 2020/05/01 | 11111102 | Jacob |
| 2020/05/01 | 11111103 | Maria |
This is my sql query
CREATE VIEW vwfrequencedatecrash AS
SELECT date_crash, num_crash, crash_scene, ROW_NUMBER() OVER (PARTITION
BY date_crash ORDER BY date_crash) AS frequence
FROM crash
ORDER BY frequence DESC;
CREATE VIEW vwmorefrequencedate AS
SELECT date_crash, num_crash, crash_scene, frequence
FROM vwfrequencedatecrash
WHERE frequence > 1;
SELECT vw.date_crash, pa.num_crash, p.name
FROM vwmorefrequencedate vw
JOIN crash c ON c.date_crash = vw.date_crash
JOIN participated pa ON c.num_crash = pa.num_crash
JOIN person p ON pa.id_person = p.id_person
ORDER BY vw.frequence DESC, c.date_crash;
how can I improve this query?

mysql query for adding non existing rows with count zero

"Table A" & "Table B" are my initial tables for the query. Result is the final table as shown in the following figure.Find Non-existing rows
Table A:
| Date | Name | Count |
|:----------:|:----:|:-----:|
| 01-01-2020 | A | 5 |
| 01-01-2020 | B | 15 |
| 02-01-2020 | B | 20 |
| 02-01-2020 | C | 15 |
| 02-01-2020 | D | 30 |
| 03-01-2020 | A | 30 |
| 03-01-2020 | D | 10 |
Table B:
| Name |
|:----:|
| A |
| B |
| C |
| D |
Result:
| Date | Name | Count |
|:----------:|:----:|:-----:|
| 01-01-2020 | A | 5 |
| 01-01-2020 | B | 15 |
| 01-01-2020 | C | 0 |
| 01-01-2020 | D | 0 |
| 02-01-2020 | A | 0 |
| 02-01-2020 | B | 20 |
| 02-01-2020 | C | 15 |
| 02-01-2020 | D | 30 |
| 03-01-2020 | A | 30 |
| 03-01-2020 | B | 0 |
| 03-01-2020 | C | 0 |
| 03-01-2020 | D | 10 |
cross join distinct dates from a to distinct id from b then left join a
drop table if exists t,t1;
create table t
(id varchar(1),dt date);
create table t1
(id varchar(1));
insert into t values
('a','2019-01-01'),('b','2019-01-01'),
('b','2019-02-01'),('d','2019-01-01'),
('c','2019-03-01');
insert into t1 values
('a'),('b'),('c'),('d');
select t3.id,t3.dt,t.id,t.dt
from
(
select distinct dt,s.id from t
cross join
(select distinct id from t1) s
) t3
left join t on t.id = t3.id and t.dt =t3.dt
order by t3.dt,t3.id;
+------+------------+------+------------+
| id | dt | id | dt |
+------+------------+------+------------+
| a | 2019-01-01 | a | 2019-01-01 |
| b | 2019-01-01 | b | 2019-01-01 |
| c | 2019-01-01 | NULL | NULL |
| d | 2019-01-01 | d | 2019-01-01 |
| a | 2019-02-01 | NULL | NULL |
| b | 2019-02-01 | b | 2019-02-01 |
| c | 2019-02-01 | NULL | NULL |
| d | 2019-02-01 | NULL | NULL |
| a | 2019-03-01 | NULL | NULL |
| b | 2019-03-01 | NULL | NULL |
| c | 2019-03-01 | c | 2019-03-01 |
| d | 2019-03-01 | NULL | NULL |
+------+------------+------+------------+
12 rows in set (0.05 sec)
PS - if you want solutions which are close to your model you should include table definitions and sample data as text in the question (which we can use) rather than links to images (which cannot use)

Mysql inner join or left join

I have 1 table products and I would like to extract price of products with type A and B. I try to use INNER JOIN but it returns duplicate record. How can I do this?
id | Price | Date | Type | Size |
-------------------------------------------------------
1 | 1,00 | 01/11/2010 | A | 7,00 |
2 | 2,50 | 02/11/2010 | A | 8,00 |
3 | 2,50 | 03/11/2010 | A | 9,00 |
4 | 3,00 | 02/11/2010 | A | 10,00 |
5 | 4,00 | 03/11/2010 | A | 11,00 |
6 | 4,00 | 03/11/2010 | A | 12,00 |
7 | 5,00 | 03/11/2010 | A | 13,00 |
8 | 5,00 | 03/11/2010 | A | 14,00 |
9 | 6,00 | 03/11/2010 | A | 15,00 |
10 | 7,00 | 03/11/2010 | A | 16,00 |
11 | 1,00 | 03/11/2010 | B | 17,00 |
12 | 2,50 | 03/11/2010 | B | 18,00 |
13 | 3,00 | 03/11/2010 | B | 19,00 |
14 | 3,00 | 03/11/2010 | B | 20,00 |
15 | 5,00 | 03/11/2010 | B | 21,00 |
16 | 6,00 | 03/11/2010 | B | 22,00 |
17 | 7,00 | 03/11/2010 | B | 23,00 |
18 | 7,00 | 03/11/2010 | B | 24,00 |
And I would like to build a table like this:
Price | Date | Size A | Size B |
-------------------------------------------------------
1,00 | 01/11/2010 | 7,00 | 17,00 |
2,50 | 02/11/2010 | 8,00 | |
2,50 | 03/11/2010 | 9,00 | 18,00 |
3,00 | 02/11/2010 | 10,00 | 19,00 |
4,00 | 03/11/2010 | 11,00 | |
4,00 | 04/11/2010 | 12,00 | |
5,00 | 03/11/2010 | 13,00 | 21,00 |
5,00 | 04/11/2010 | 14,00 | |
6,00 | 05/11/2010 | 15,00 | |
7,00 | 06/11/2010 | 16,00 | 23,00 |
How can I do that in one query?
Thanks for any help.
select price,
date,
sum(case when `type` = 'A' then size else 0 end) as SizeA,
sum(case when `type` = 'B' then size else 0 end) as SizeB
from products
group by price, date
order by price, date
Group by the date to get the data for each date. To get the other columns you need to use aggregate functions like sum().
If you really need the null values you can do:
case when sum(`type` = 'A') = 0
then null
else sum(case when `type` = 'A' then size end)
end

How to query for matching record sets

I am trying to do a query to find people living at the same address. But my SQL appears to fail and not sure why.
mysql> SELECT * FROM polished1 WHERE LName = 'BENDICH'; +------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+
| id | StateVoterID | Title | FName | MName | LName | NameSuffix | Birthdate | Gender | RegStNum | RegStFrac | RegStPreDirection | RegStName | RegStType | RegStPostDirection | RegUnitType | RegUnitNum | RegCity | RegState | RegZipCode | CountyCode | PrecinctPart | LegislativeDistrict | CongressionalDistrict | Mail1 | Mail2 | Mail3 | Mail4 | MailCity | MailZip | MailCountry | Registrationdate | AbsenteeType | LastVoted | StatusCode |
+------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+
| 2790 | 72253 | | ARNOLD | J | BENDICH | | 5 | M | 1754 | | NE | 2ND | ST | | | 0 | SEATTLE | WA | 98115 | 2071 | 43 | 7 | | | | | | | | 10/1/1965 | P | 2/12/2013 | A | NULL |
| 2791 | 72253 | | JUDITH | E | BENDICH | | 1 | F | 1754 | | NE | 2ND | ST | | | 0 | SEATTLE | WA | 98115 | 2071 | 43 | 7 | | | | | | | | 10/1/1965 | P | 2/12/2013 | A | NULL |
+------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+
2 rows in set (0.00 sec)
mysql> SELECT *, COUNT(*) c FROM polished1 WHERE LName = 'Bendich' GROUP BY RegStNum, RegStName, RegStType, RegUnitType, RegStPreDirection, RegStPostDirection, RegUnitNum, RegCity, RegState, RegZipCode HAVING c > 1;
+------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+---+
| id | StateVoterID | Title | FName | MName | LName | NameSuffix | Birthdate | Gender | RegStNum | RegStFrac | RegStPreDirection | RegStName | RegStType | RegStPostDirection | RegUnitType | RegUnitNum | RegCity | RegState | RegZipCode | CountyCode | PrecinctPart | LegislativeDistrict | CongressionalDistrict | Mail1 | Mail2 | Mail3 | Mail4 | MailCity | MailZip | MailCountry | Registrationdate | AbsenteeType | LastVoted | StatusCode | c |
+------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+---+
| 2790 | 72253 | | ARNOLD | J | BENDICH | | 5 | M | 1754 | | NE | 2ND | ST | | | 0 | SEATTLE | WA | 98115 | 2071 | 43 | 7 | | | | | | | | 10/1/1965 | P | 2/12/2013 | A | NULL | 2 |
+------+--------------+-------+--------+-------+---------+------------+-----------+--------+----------+-----------+-------------------+-----------+-----------+--------------------+-------------+------------+---------+----------+------------+------------+--------------+---------------------+-----------------------+-------+-------+-------+-------+----------+---------+-------------+------------------+--------------+-----------+------------+---+
1 row in set (0.01 sec)
http://bpaste.net/show/UWC8wdOWMbFEQcT7eV6f/
select p.*
from polished1 p JOIN
(
SELECT *, COUNT(*) c
FROM polished1
WHERE LName = 'Bendich'
GROUP BY RegStNum, RegStName, RegStType, RegUnitType, RegStPreDirection, RegStPostDirection, RegUnitNum, RegCity, RegState, RegZipCode
HAVING c > 1) filtered ON p.RegStNum=filtered.RegStNum
and p.RegStName=filtered.RegStName
and p.RegStType=filtered.RegStType
and p.RegUnitType=filtered.RegUnitType
and p.RegStPreDirection=filtered.RegStPreDirection
and p.RegStPostDirection=filtered.RegStPostDirection
and p.RegUnitNum=filtered.RegUnitNum
and p.RegCity=filtered.RegCity
and p.RegState=filtered.RegState
and p.RegZipCode=filtered.RegZipCode
You should retrieve the addresses where count(*)>1 first and then get all joined addresses