sql查询语法case、join和group by

str*_*ner 3 mysql sql

我有两个 mysql 表:

mysql> desc macToNames;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| mac   | varchar(17)   | YES  | UNI | NULL    |       |
| Name  | text          | YES  |     | NULL    |       |
| Seen  | decimal(10,0) | NO   |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)

mysql> desc stats;
+--------+---------------+------+-----+---------+-------+
| Field  | Type          | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| mac    | varchar(17)   | YES  |     | NULL    |       |
| ipAddr | text          | YES  |     | NULL    |       |
| epoch  | decimal(10,0) | NO   |     | NULL    |       |
| sent   | decimal(10,0) | NO   |     | NULL    |       |
| recv   | decimal(10,0) | NO   |     | NULL    |       |
+--------+---------------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)

由于本人水平有限,有如下疑问join

select case when macToNames.Name is null then stats.mac else macToNames.Name end as 'Hostname'
     ,stats.mac as 'mac',stats.ipAddr as 'ipAddr'
     ,stats.epoch as 'epoch'
     ,stats.sent as 'sent'
     ,stats.recv as 'recv' 
  from stats 
  left
  join macToNames 
    on macToNames.mac = stats.mac
  limit 5;
+-------------------+-------------------+---------------+------------+----------+-----------+
| Hostname          | mac               | ipAddr        | epoch      | sent     | recv      |
+-------------------+-------------------+---------------+------------+----------+-----------+
| x1                | 39-F2-BC-2F-4D-E9 | 192.168.1.232 | 1593836118 |   307197 |    623309 |
| someho-lxc        | 29-F2-BC-2F-4D-E9 | 192.168.1.52  | 1593836118 |  4273599 |   4207535 |
| 39-F2-BC-2F-4D-E9 | 39-F2-BC-2F-4D-E9 | 192.168.1.216 | 1593836118 |     4899 |      6503 |
| tinker            | 39-F2-AC-2F-4D-E9 | 192.168.1.166 | 1593836119 |    60312 |   8563601 |
| u1                | 3A-F2-BC-2F-4D-E9 | 192.168.1.172 | 1593836119 |      380 |       380 |
+-------------------+-------------------+---------------+------------+----------+-----------+
Run Code Online (Sandbox Code Playgroud)

这对我来说是困难的地方 - 我希望将上面的查询作为子查询运行

mysql> select Hostname,mac from (select case when macToNames.Name is null then stats.mac else macToNames.Name end as 'Hostname',stats.mac as 'mac',stats.ipAddr as 'ipAddr',stats.epoch as 'epoch',stats.sent as 'sent',stats.recv as 'recv' from stats left join macToNames on macToNames.mac=stats.mac);
ERROR 1248 (42000): Every derived table must have its own alias
Run Code Online (Sandbox Code Playgroud)

还有,另一个:

mysql> select Hostname,mac,sum(stats.Sent)/(1000000000) as 'Sent',sum(stats.Recv)/1000000000 as 'Recv' group by mac from (select case when macToNames.Name is null then stats.mac else macToNames.Name end as 'Hostname',stats.mac as 'mac',stats.ipAddr as 'ipAddr',stats.epoch as 'epoch',stats.sent as 'sent',stats.recv as 'recv' from stats left join macToNames on macToNames.mac=stats.mac);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group by mac from (select case when macToNames.Name is null then stats.mac else ' at line 1
Run Code Online (Sandbox Code Playgroud)

我正在尝试生成每台 Mac 的总流量报告,并显示该设备的友好名称。我在案件和加入之间完全迷失了 - 你能给我指出正确的方向吗?

Par*_*ait 5

FROM正如错误所示,您必须为or子句中的派生表或子查询提供别名JOIN。此外,对于聚合查询,所有SELECT列都必须出现在GROUP BY(其后面的FROMJOIN子句)中。请注意,下面顶层的所有列均由别名限定sub。此外,字段的列别名stats是多余的,因为没有使用表达式并且它们重复原始列名称。最后,对于许多零,E为了可读性而使用。

select sub.Hostname
       , sub.mac
       , sum(sub.Sent)/1E9 as 'Sent'
       , sum(sub.Recv)/1E9 as 'Recv' 
from 
  (select case 
              when macToNames.Name is null 
              then stats.mac 
              else macToNames.Name 
           end as 'Hostname'
           , stats.mac
           , stats.ipAddr
           , stats.epoch
           , stats.sent
           , stats.recv
    from stats 
    left join macToNames 
         on macToNames.mac=stats.mac
  ) as sub
group by sub.Hostname
       , sub.mac
Run Code Online (Sandbox Code Playgroud)

在 MySQL 8.0+ 中,您可以使用CTE代替派生表:

with sub AS (
   select case 
            when macToNames.Name is null 
            then stats.mac 
            else macToNames.Name 
          end as 'Hostname'
          , stats.mac
          , stats.ipAddr
          , stats.epoch
          , stats.sent
          , stats.recv
   from stats 
   left join macToNames 
         on macToNames.mac=stats.mac)

select sub.Hostname
       , sub.mac
       , sum(sub.Sent)/1E9 as 'Sent'
       , sum(sub.Recv)/1E9 as 'Recv' 
from sub
group by sub.Hostname
       , sub.mac
Run Code Online (Sandbox Code Playgroud)