MySQL - calculate percent of a column with multiple column grouping - mysql

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.

Related

How do i show values from the table

how do i show all values from this table
+------+---------+-------+--------+-----+
| A | B | C | D | E |
+------+---------+-------+--------+-----+
| 2 | K | M | NULL | S |
| 3 | L | C | NULL | N |
| 4 | R | P | NULL | N |
| 5 | P | N | C | N |
| 6 | Y | Q | NULL | S |
| 7 | S | T | NULL | S |
| 8 | C | M | NULL | N |
| 9 | X | C | NULL | S |
| 10 | E | Q | NULL | N |
| 11 | A | C | NULL | S |
| 12 | C | NULL | C | N |
| 13 | F | Q | NULL | N |
| 14 | L | NULL | C | S |
| 15 | S | P | NULL | S |
+------+---------+-------+--------+-----+
to this.
show the first 8 values from column A, B and the 7 will be 5 in column A
SELECT A, B FROM letters LIMIT 8;
+------+--------+
| A | B |
+------+--------+
| 2 | K |
| 3 | L |
| 4 | R |
| 5 | P |
| 6 | Y |
| 5 | S |
| 8 | C |
| 9 | X |
+------+--------+
You'll want to use a case expression or the if() function. My preference is a case expression because it's more portable. Furthermore you'll need to supply an ORDER BY clause since records in a table have no ordering.
SELECT CASE WHEN A=7 THEN 5 ELSE A END as A, B FROM letters ORDER BY letters.A LIMIT 8;

How to display all duplicate value

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

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 Complex Join one-to-many

I have the following tables:
clients:
| id | name | code | zone |
--------------------------------
| 1 | client 1 | a1b1 | zone1|
| 2 | client 2 | a2b2 | zone2|
contacts:
| id_contact | first_name | last_name |
----------------------------------------
| 11 | first1 | last1 |
| 22 | first2 | last2 |
| 33 | first3 | last3 |
| 44 | first4 | last4 |
client_contacts:
| id_client | id_contact |
--------------------------
| 1 | 11 |
| 1 | 22 |
| 1 | 33 |
| 2 | 11 |
| 2 | 44 |
offers:
| id_offer | id_client | value |
--------------------------
| 111 | 1 | 100 |
| 222 | 1 | 200 |
| 333 | 1 | 300 |
| 444 | 2 | 400 |
I would like through a optimal select to obtain:
| id_client | name | code | zone | contacts_pers | total_offer_value |
----------------------------------------------------------------------------
| 1 | client 1 | a1b1 | zone1 | first1 last1; | 600 |
first2 last2;
first3 last3;
| 2 | client 2 | a2b2 | zone2 | first1 last1; | 400 |
first4 last4;
I know how to get the desired result with "group_concat" and stored procedures for "total_offer_value". But how to get the desired result from a single efficient select?
SELECT c.id, c.name, c.code, c.zone, GROUP_CONCAT(DISTINCT CONCAT(co.first_name, " ", c.last_name) SEPARATOR ";") AS contact_pers, func_total_offer_value(c.id) AS total_offer_value
FROM clients c
LEFT OUTER JOIN (client_contacts cc, contacts co) ON ( c.id = cc.id_client AND cc.id_contact = co.id_contact )
GROUP BY c.id

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