简体   繁体   中英

SQL: Group by multiple fields

I need to select some values, group them and order by multiple fields. Here is my fiddle: http://sqlfiddle.com/#!2/a80eb/3

What I need to achieve, is to select one row from the table packet_data for a given value of client_mac and for each distinct item in the column drone_id . This row should contain the value of client_mac , drone_id and the most frequent value of the antenna_signal column for the given combination of drone_id and client_mac .

The column drone_id is a foreign key into the table drones and there is a column map_id in this table. I need to concern only those rows from the packet_data table which have a certain map_id in the drones table.

My desired result should be this:

CLIENT_MAC          DRONE_ID    ANTENNA_SIGNAL
3c:77:e6:17:9d:1b   1           -37
3c:77:e6:17:9d:1b   2           -57

My current SQL query is:

SELECT `packet_data`.`client_mac`,
       `packet_data`.`drone_id`,
       `packet_data`.`antenna_signal`,
       count(*) AS `count`
FROM `packet_data`
JOIN `drones` ON `packet_data`.`drone_id`=`drones`.`custom_id`
WHERE `drones`.`map_id` = 11
  AND `client_mac`="3c:77:e6:17:9d:1b"
GROUP BY drone_id,
         `packet_data`.`antenna_signal`
ORDER BY `packet_data`.`drone_id`,
         count(*) DESC

And my current result:

CLIENT_MAC          DRONE_ID    ANTENNA_SIGNAL
3c:77:e6:17:9d:1b   1           -37
3c:77:e6:17:9d:1b   1           -36
3c:77:e6:17:9d:1b   2           -57
3c:77:e6:17:9d:1b   2           -56

You can get your desired result with a not very nice correlated subquery (on a subquery too). I don't know how it will be scaling with a huge amount of data:

SELECT
    -- the desired columns
    client_mac,
    drone_id,
    antenna_signal,
    amount               -- I added this so I could easily check the result
FROM (
    -- give me the count of every value of the antenna_signal column 
    -- for each combination of client_mac, drone_id and antenna_signal
    SELECT 
        client_mac,
        antenna_signal,
        drone_id,
        COUNT(antenna_signal) AS amount
    FROM
        packet_data
    WHERE
        client_mac = '3c:77:e6:17:9d:1b'
    GROUP BY
        client_mac,
        drone_id,
        antenna_signal
) as1
WHERE
    -- but I want only those rows with the highest count of equal antenna_signal
    -- values per client_mac and drone_id
    amount = (
        SELECT 
            MAX(as2.amount)
        FROM (
            SELECT 
                pd2.client_mac,
                pd2.antenna_signal,
                pd2.drone_id,
                COUNT(pd2.antenna_signal) AS amount
            FROM
                packet_data pd2
            WHERE
                client_mac = '3c:77:e6:17:9d:1b'
            GROUP BY
                client_mac,
                drone_id,
                antenna_signal
            ) as2
        WHERE 
            as1.client_mac = as2.client_mac AND as1.drone_id = as2.drone_id
);

It shouldn't be too difficult to join other tables if it is desired. But this will display both rows, if there are two antenna_signals with equal count for the same client_mac and drone_id. See it in the updated fiddle http://sqlfiddle.com/#!2/a80eb/80

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