MySQL - How to limit one result per ID?

前端 未结 2 463
悲哀的现实
悲哀的现实 2021-01-23 01:40

I have the following query which creates a view table showing the highest salesperson in a store with few other details:

CREATE OR REPLACE VIEW sales_data AS 
SE         


        
相关标签:
2条回答
  • 2021-01-23 02:19
    CREATE OR REPLACE VIEW employee_sales_totals AS
        SELECT
            e.*,
            SUM(p.total_sale_value)   AS total_sale_value
        FROM
            Employee e
        INNER JOIN
            Payment  p
                ON p.employee_number = e.employee_number 
        GROUP BY
            e.id  -- This should be the Primary Key / Surrogate Key of the employee table
    ;
    
    CREATE OR REPLACE VIEW shop_top_employee_by_sales_value AS
        SELECT
            s.storename          AS "Store", 
            e.employee_name      AS "Employee", 
            m.employee_name      AS "Manager", 
            p.total_sale_value   AS "Sales Value" 
        FROM
        (
            SELECT storeid, MAX(total_sale_value) AS total_sale_value
              FROM employee_sales_totals
          GROUP BY storeid
        )
           p
        INNER JOIN
            employee_sales_totals   e
                ON  e.storeid          = p.storeid
                AND e.total_sale_value = p.total_sale_value
        INNER JOIN
            fss_Shop   s 
                ON s.storeid = e.storeid 
        INNER JOIN
            Employee   m
                ON m.employee_number = e.manager_number 
    ;
    

    As per the answer to your previous question, if multiple employees are tied for the same total sales amount in the same store, all such employees would be returned.

    0 讨论(0)
  • 2021-01-23 02:32

    Consider using a ranking variable by SalesValue for each employee per store and then choose the RANK=1 in outer query:

    SELECT main.Store, main.Employee, main.Manager, main.SalesValue
    FROM
     (SELECT agg.*,      
             @store:=agg.Store AS CURR_STORE,
             @rank:=CASE WHEN @val > agg.SalesValue THEN @rank+1 ELSE 1 END AS RANK,
             @val:=CASE WHEN @store <> agg.Store THEN @val ELSE agg.SalesValue END AS CURR_VAL
      FROM
        (SELECT s.storename AS "Store", 
                e.employee_name AS "Employee", 
                e1.employee_name AS "Manager", 
                SUM(p.total_sale_value) AS "SalesValue"
         FROM fss_Shop s 
         INNER JOIN Employee e ON e.storeid = s.storeid 
         INNER JOIN Payment p ON p.employee_number = e.employee_number 
         INNER JOIN Employee e1 ON e1.employee_number = e.manager_number  
         GROUP BY s.storename, 
                  e.employee_name, 
                  e1.employee_name
        ) As agg
      CROSS JOIN (SELECT @rank:= 0) AS r1
      CROSS JOIN (SELECT @val:= 0) AS r2
      CROSS JOIN (SELECT @store:= 0) AS r3
      ORDER BY agg.Store, agg.SalesValue DESC
     ) As main
    WHERE main.RANK = 1; 
    

    DEMO

    Rextester (using random data with only one Sales table)


    Alternatively, if variables cannot be used, consider creating two views where latter references the former: 1) initial aggregate query, 2) correlated subquery to retrieve top employee per store

    CREATE OR REPLACE VIEW sales_data AS 
    SELECT s.storename AS "Store", 
           e.employee_name AS "Employee", 
           e1.employee_name AS "Manager", 
           SUM(p.total_sale_value) AS "SalesValue"
    FROM fss_Shop s 
    INNER JOIN Employee e ON e.storeid = s.storeid 
    INNER JOIN Payment p ON p.employee_number = e.employee_number 
    INNER JOIN Employee e1 ON e1.employee_number = e.manager_number  
    GROUP BY s.storename, 
             e.employee_name, 
             e1.employee_name;
    
    CREATE OR REPLACE VIEW top_sales_data AS 
    SELECT s.*
    FROM sales_data s 
    WHERE (SELECT Count(*) FROM sales_data sub
           WHERE sub.SalesValue > s.SalesValue 
           AND sub.Store = s.Store) = 0;
    
    0 讨论(0)
提交回复
热议问题