简体   繁体   中英

Getting ratios in mysql without subqueries

I would like to run a query from the tables below that gives me the ratio of the amount paid from the executive offices to the total amount due:

 CREATE TABLE  offices (
   name VARCHAR(255),
   ID VARCHAR(255),
  level VARCHAR(255)
 );



 INSERT INTO offices (name,ID,level)
   VALUES 
  ('chairman', 'ad1', 'admin'),
  ('MD', 'ad2', 'admin'),
  ('CEO', 'ad3', 'admin'),
  ('president', 'ex1', 'exec' ),
  ('VP', 'ex2', 'exec'),
  ('GM', 'ex3', 'exec'),
  ('HOD', 'ex4', 'exec');

CREATE TABLE  cheques (
  payee VARCHAR(255) ,
 officeID VARCHAR(255),
 amount INT(),
 status VARCHAR(255) 
 );


INSERT INTO cheques
 VALUES ('john', 'ad2', '100',  'paid'),
 ('john',   'ad3',  '50',   'owed'),
 ('john',   'ex3',  '80',   'paid'),
 ('john',   'ex4',  '150',  'owed'),
 ('john',   'ex1',  '35',   'paid'),
('mary',    'ad1',  '200',  'paid'),
('mary',    'ad3',  '90',   'owed'),
('mary',    'ex2',  '110',  'paid'),
('mary',    'ex4',  '40',   'owed'),
('mary',    'ex1',  '60',   'paid'),
('jane',    'ad1',  '75',   'paid'),
('jane',    'ad3',  '120',  'paid');

The expected result is as below:

data.frame(
 payee=c("john","mary"),
 totalpaid=c(115,170),
 status=c("paid", "paid"),
 totalsdue = c(415, 500),
 ratio=(0.28, 0.34)
   )

I have been able to get totalpaid from exec offices as below

  SELECT c.payee, SUM(c.amount) as totalpaid, c.status
   FROM cheques c
   JOIN offices o
   ON c.officeID = o.ID
  WHERE 
   o.level LIKE '%ex%'
 AND 
   c.status LIKE '%paid%'
 GROUP BY payee 

and the totalsdue as below

   SELECT  c.payee, SUM(c.amount) as totalsdue
     FROM cheques c
      GROUP BY payee

What I have tried without success:

  SELECT  
   c.payee, SUM(c.amount) as totalsdue
      totalsdue/totalpaid as ratio
      FROM cheques c
      WHERE c.payee IN
        (SELECT c.payee, SUM(c.amount) as totalpaid, c.status
           FROM cheques c
           JOIN offices o
           ON c.officeID = o.ID
           WHERE 
             o.level LIKE '%ex%'
           AND 
             c.status LIKE '%paid%'
          GROUP BY payee )
      GROUP BY payee

How to get the expected results with a single query.

I would like to run a query from the tables below that gives me the ratio of the amount paid from the executive offices to the total amount due.

I think you just want window functions:

SELECT c.payee, SUM(c.amount) as totalsdue,
       SUM(c.amount) / SUM(SUM(c.amount)) OVER () as ratio
FROM cheques c
GROUP BY payee;

You have other conditions in your queries, but they are not explained in the question.

For the result you could use the subquery in JOIN

  SELECT t1.payee, t1.totalsdue, t1.totalsdue/t2.totalpaid 
  from  (
      SELECT  c.payee, SUM(c.amount) as totalsdue
      FROM cheques c
      GROUP BY payee
  ) t1
  INNER JOIN  (
    SELECT c.payee, SUM(c.amount) as totalpaid, c.status
    FROM cheques c
    JOIN offices o  ON c.officeID = o.ID
    WHERE o.level LIKE '%ex%'
    AND   c.status LIKE '%paid%'
    GROUP BY payee 
 ) t2 on t1.payee = t2.payee 

for better performance..
check if you really need like and wildchar matching or you can result ve the query with exact matching

and be sure you have proper index on columns potenzially involved in join and where

table cheques column ( officeID, payee)

or if the column status allow exact match column ( officeID, status, payee)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM