简体   繁体   中英

MariaDB (MySQL) “AVG” not working with HAVING

My question is: Why do the following two SQL statements produce different results (I am explaining both afterwards. Tested with MariaDB bundeled with XAMPP 7.0.8)

(1)

SELECT
stock_exchange_code,
summed
FROM (
   SELECT
     stock_exchange_code,
     summed
   FROM (
          SELECT
            STOCK_EXCHANGE_CODE,
            sum(SHARE_PRICE * SHARE_CNT) AS summed
          FROM LISTED_AT
          WHERE DATE_VALID = STR_TO_DATE('04-12-2015', '%d-%m-%Y')
          GROUP BY STOCK_EXCHANGE_CODE
        ) a) b
HAVING summed > avg(summed)

(2)

SELECT
stock_exchange_code,
summed
FROM (
   SELECT
     STOCK_EXCHANGE_CODE,
     sum(SHARE_PRICE * SHARE_CNT) AS summed
   FROM LISTED_AT
   WHERE DATE_VALID = STR_TO_DATE('04-12-2015', '%d-%m-%Y')
   GROUP BY STOCK_EXCHANGE_CODE
 ) a
WHERE summed > (SELECT avg(a.summed)
            FROM (SELECT
                    sum(SHARE_PRICE * SHARE_CNT) AS summed
                  FROM LISTED_AT
                  WHERE DATE_VALID = STR_TO_DATE('04-12-2015', '%d-%m-%Y')
                  GROUP BY STOCK_EXCHANGE_CODE) a)

Result of those queries: (1) will give you an empty set (I do not understand why) (2) will give you 2 rows, which is the correct answer

Explanation of the 2 Select statements:

  SELECT
     STOCK_EXCHANGE_CODE,
     sum(SHARE_PRICE * SHARE_CNT) AS summed
   FROM LISTED_AT
   WHERE DATE_VALID = STR_TO_DATE('04-12-2015', '%d-%m-%Y')
   GROUP BY STOCK_EXCHANGE_CODE

This is the part of the Select statement, which sums up all share values at a specific stock exchange. The output is:

BRX 122653.50

L&S 275000.00

MXK 500000.00

STU 140415.00

XETRA 254610.00

And AVG(summed) = 258535.6

With statement (1) [which I tried first) I use an select around to be certain that the group by is global. Looking at it now, there is one unnecessary "serlect all columns by name", bur this should not matter here. With the outer select I try to apply the "HAVING" clause.

I do want all stock exchanges which summed value ( => "summed") on a specific day is above average. As far as I understand HAVING, it should calculate the global average ( => of the 5 stock exchanges above) and check against that.

I do not know, why this is not working. Changing the summed > avg(summed) to summed <> avg(summed) results in one row ( BRX 122653.50). summed > 0 results in all 5 rows returned. This is the reason why I think the average does not work with the having and not the other way round.

(2) This is quite the same as the first, replacing the HAVING clause with an more explecit average calculation. As you can see there are 2 subqueries with the name "a" and both are the same (the second one lacks the stock_exchange_code field. Practically this query is ident with the first one, with worse code quality than the first one (duplication).

My question is: For me the 2 queries should have an identical result. Why do they have a different result?

tl;dr

Average or having clause does not seem to work in MySQL (MariaDB). Why do the 2 SQL statements from the beginning not return the same?

The use of an aggregate triggers grouping the entire table into one row. That is, HAVING summed > avg(summed) causes it to be one row, not some subset of the collection of rows. Hence, #1 is probably not useful.

In the second query, spelling out the avg(summed) as SELECT ... is generating one value that is then used for each row.

It seems that you have an extra level of SELECTs in both queries.

You can use EXPLAIN SELECT ... to get more clues on what is going on.

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