SQL Having on columns not in SELECT

Rapsey picture Rapsey · Jul 14, 2011 · Viewed 9.9k times · Source

I have a table with 3 columns:

userid   mac_address   count

The entries for one user could look like this:

57193   001122334455   42
57193   000C6ED211E6   15
57193   FFFFFFFFFFFF   2

I want to create a view that displays only those MAC's that are considered "commonly used" for this user. For example, I want to filter out the MAC's that are used <10% compared to the most used MAC-address for that user. Furthermore I want 1 row per user. This could easily be achieved with a GROUP BY, HAVING & GROUP_CONCAT:

SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
FROM mactable
GROUP BY userid
HAVING count*10 >= MAX(count)

And indeed, the result is as follows:

57193   001122334455,000C6ED211E6   42

However I really don't want the count-column in my view. But if I take it out of the SELECT statement, I get the following error:

#1054 - Unknown column 'count' in 'having clause'

Is there any way I can perform this operation without being forced to have a nasty count-column in my view? I know I can probably do it using inner queries, but I would like to avoid doing that for performance reasons.

Your help is very much appreciated!

Answer

Daniel Hilgarth picture Daniel Hilgarth · Jul 14, 2011

As HAVING explicitly refers to the column names in the select list, it is not possible what you want.
However, you can use your select as a subselect to a select that returns only the rows you want to have.

SELECT a.userid, a.macs
FROM
(
    SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
    FROM mactable
    GROUP BY userid
    HAVING count*10 >= MAX(count)
) as a

UPDATE:
Because of a limitation of MySQL this is not possible, although it works in other DBMS like Oracle. One solution would be to create a view for the subquery. Another solution seems cleaner:

CREATE VIEW YOUR_VIEW (userid, macs) AS
SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
FROM mactable
GROUP BY userid
HAVING count*10 >= MAX(count)

This will declare the view as returning only the columns userid and macs although the underlying SELECT statement returns more columns than those two.
Although I am not sure, whether the non-DBMS MySQL supports this or not...