Home > Enterprise >  SQL average number of rows
SQL average number of rows

Time:01-06

I need to display the Lastname when the total number of ordered products in 1 order is greather than 2 and I need to calculate the avg of commanded products. The output must be :


 | LASTNAME | AVG  |
--------------------
 | SMITH    | 2.5  |
 | HARRIS| 2.75 |
------------------

I'm trying this

   SELECT c.customer_id,firstname,lastname,count(o.order_id)*1.0/(select distinct count(*)FROM ORDERS where order_id=o.order_id)
   FROM customer c,PURCHASES p,ORDERS o
   WHERE c.customer_id=p.customer_id and p.order_id=o.order_id
        and  o.order_id in (SELECT order_id
        FROM ORDERS
        GROUP BY order_id
        HAVING COUNT(*) > 2)
  group by c.customer_id

It seems to be correct, but I get incorrect answer.

Here is the table of relation between CUSTOMER and ORDERS


| LASTNAME | ORDER_ID | PRODUCT_ID  |
------------------------------------
| SMITH    | 0        | 91          |
| SMITH    | 0        | 122         |
| WILLIAMS | 1        | 179         |
| SMITH    | 2        | 50          |
| SMITH    | 2        | 43          |
| SMITH    | 2        | 200         |
| HARRIS   | 3        | 105         |
| HARRIS   | 3        | 173         |
| HARRIS   | 4        | 29          |
| HARRIS   | 4        | 158         |
| JACKSON  | 5        | 75          |
| WILLIAMS | 6        | 55          |
| HARRIS   | 7        | 86          |
| HARRIS   | 7        | 143         |
| HARRIS   | 7        | 152         |
| HARRIS   | 7        | 197         |
| HARRIS   | 7        | 198         |
| BROWN    | 8        | 149         |
| HARRIS   | 9        | 117         |
| HARRIS   | 9        | 177         |
| WILLIAMS | 10       | 116         |
| JACKSON  | 11       | 13          |
| JACKSON  | 11       | 188         |
| WILLIAMS | 12       | 17          |
| WILLIAMS | 12       | 89          |
------------------------------------

CodePudding user response:

DBFIDDLE

SELECT LASTNAME, Products/Orders
FROM (
   SELECT 
      LASTNAME,
      COUNT(DISTINCT ORDER_ID) Orders,
      COUNT(PRODUCT_ID) Products
   FROM Table1
   GROUP BY LASTNAME
   )x
WHERE LASTNAME IN (
   SELECT LASTNAME
   FROM (
      SELECT 
        LASTNAME,
        COUNT(PRODUCT_ID) OVER (PARTITION BY LASTNAME,ORDER_ID) c
      FROM Table1
    )x
   WHERE c>=3
)

result:

LASTNAME Average
HARRIS 2.7500
SMITH 2.5000

CodePudding user response:

This will work for MySQL >= 8

# gets all usernames which have have at least one order with more than two items
with users(name) as (
  select distinct name
  from orders
  group by name, orderid
  having count(productid) > 2
),
# gets the size of each order for the names
ordersize(name, productcount) as (
  select u.name, count(productid)
  from users u inner join orders o on u.name = o.name
  group by u.name, orderid
)
# get the average of productcount
select name, avg(productcount)
from ordersize
group by name

See also this Fiddle

CodePudding user response:

Example here for MySQL > 8.0. DDL is in the linked Fiddle - I've gone off Customer_ID instead of Lastname, because the latter wouldn't really work in real life.

-- First CTE - Get the customers with two or more orders
WITH cte1 AS
(
   SELECT
     Customer_ID,
     COUNT(DISTINCT Order_ID) AS OrderCount
   FROM
     CustomerOrder
  GROUP BY 
      Customer_ID
  HAVING 
     COUNT(DISTINCT Order_ID) >= 2
), cte2 AS
-- Get product counts per order
(
  SELECT 
      co.Customer_ID, 
      co.Order_ID,
      COUNT(DISTINCT Product_ID) AS Products
  FROM 
      CustomerOrder co
  INNER JOIN 
      cte1
  ON  cte1.Customer_ID = co.Customer_ID
  GROUP BY
    co.Customer_ID,
    co.Order_ID
)
-- Finally, average products per order
SELECT Customer_ID, AVG(Products) AS AverageProductsInOrder
FROM cte2
GROUP BY 
    Customer_ID;

https://www.db-fiddle.com/f/dKkSN5H9DioyouAppAErn1/0

CodePudding user response:

declare @tmp as table(LASTNAME varchar(20),ORDER_ID int, PRODUCT_ID int)

insert into @tmp values('SMITH',    0        , 91          )
,('SMITH',    0        , 122         )
,('WILLIAMS', 1        , 179         )
,('SMITH',    2        , 50          )
,('SMITH',    2        , 43          )
,('SMITH',    2        , 200         )
,('HARRIS',   3        , 105         )
,('HARRIS',   3        , 173         )
,('HARRIS',   4        , 29          )
,('HARRIS',   4        , 158         )
,('JACKSON',  5        , 75          )
,('WILLIAMS', 6        , 55          )
,('HARRIS',   7        , 86          )
,('HARRIS',   7        , 143         )
,('HARRIS',   7        , 152         )
,('HARRIS',   7        , 197         )
,('HARRIS',   7        , 198         )
,('BROWN',    8        , 149         )
,('HARRIS',   9        , 117         )
,('HARRIS',   9        , 177         )
,('WILLIAMS', 10       , 116         )
,('JACKSON',  11       , 13          )
,('JACKSON',  11       , 188         )
,('WILLIAMS', 12       , 17          )
,('WILLIAMS', 12       , 89          )

select LASTNAME, 
sum(numerator),
count(*),
sum(numerator)/cast(count(*) as decimal(18,3)) avg
FROM
(
select 
LASTNAME,ORDER_ID, COUNT(*) numerator
from @tmp tmp

where tmp.LASTNAME
IN
(
select LASTNAME from @tmp tmp2
group by LASTNAME
having count(*)>2
)
GROUP BY LASTNAME,ORDER_ID
)x
GROUP BY LASTNAME
having sum(numerator)/cast(count(*) as decimal(18,3))>2
ORDER BY LASTNAME

output:

LASTNAME    (No column name)    (No column name)    avg
HARRIS  11  4   2.7500000000000000000
SMITH   5   2   2.5000000000000000000
  •  Tags:  
  • Related