MySQL:根据子查询的相关子查询获取行计数

时间:2011-04-27 21:19:21

标签: mysql count correlated-subquery

我道歉,如果已经回答了其他地方,我一直在寻找我的头发,但还没找到任何东西。

我有以下表格:

    Table: STATES
+------------+---------+
| name       | stateID |
+------------+---------+
| Florida    |  FL     |
| California |  CA     |
| New Jersey |  NJ     |
+------------+---------+

Table: AREAS
+-------+---------+-------+
| name  | stateID | locID |
+-------+---------+-------+
| Area1 | FL      | 1     |
| Area2 | FL      | 1     |
| Area3 | FL      | 2     |
| Area4 | NJ      | 3     |
| Area5 | NJ      | 3     |
| Area6 | NJ      | 4     |
| Area7 | CA      | 5     |
| Area8 | CA      | 6     |
| Area9 | CA      | 7     |
+-------+---------+-------+

Table: LOCATIONS
+----------+-------+
| name     | locID |
+----------+-------+
| Orlando  | 1     |
| Brevard  | 2     |
| North NJ | 3     |
| South NJ | 4     |
| B Hills  | 5     |
| East LA  | 6     |
| SanFran  | 7     |
+----------+-------+

我想要的结果是:

| STATES.name | LOCATIONS.name | COUNT(locations in state) | AREAS.name

我能够轻松地获得除了计数之外的所有内容,但我无法知道每个州有多少个位置。看起来这应该是一件简单的事情,我只是错过了什么?

以下是我一直在使用的查询:

SELECT 
    STATES.name AS state
    ,LOCATIONS.name AS location
    ,AREAS.name AS area
    ,(SELECT
        COUNT(*) 
     FROM 
        (SELECT
            areaID
        FROM
            AREAS
        WHERE 
            AREAS.stateID = STATES.stateID 
         GROUP BY 
            AREAS.locID
        ) AS area_count

    ) AS row_count
FROM
    STATES
    LEFT JOIN AREAS ON STATES.stateID = AREAS.stateID
    LEFT JOIN LOCATIONS ON AREAS.locID = LOCATIONS.locID;

当然这会失败,因为子查询1中没有任何STATES.stateID可供引用子查询2。我已经尝试通过JOIN在子查询1中的表传递stateID,以及JOIN在子查询2中传递它,而不是尝试在WHERE语句中引用它。鉴于整个子查询2是子查询1的WHERE语句的一部分,这也失败了......

我也尝试将查询隔离到仅提取AREAS.stateIDCOUNT(locations in state),但无济于事,我不断获取州内的区域数量,而不是位置数量:

select AREAS.stateID
, COUNT(AREAS.locID)
FROM AREAS group by AREAS.stateID

DISTINCT扔进COUNT()让我更接近,但有些值仍然关闭,不知道从哪里获取数字,因为它们与所有案例的位置数不匹配,但大多数......

2 个答案:

答案 0 :(得分:1)

如果我理解正确:

  • 每个州都有很多地方 (1对多的关系)

  • 每个位置都有很多区域 (1对多的关系)

因此,表stateID中应该有一个Location,作为表State的外键。

stateID

中不需要Area

然后,你可以:

SELECT
    s.name         AS stateName
  , l.name         AS locationName
  , locgrp.locCnt  AS locationsInState           
  , a.name         AS areaName
FROM STATES s
  JOIN LOCATIONS l
    ON s.stateID = l.stateID
  JOIN AREAS a
    ON a.locationID = l.locationID
  LEFT JOIN 
    ( SELECT stateID
           , COUNT(*) AS locCnt
      FROM LOCATIONS 
      GROUP BY stateID
    ) locgrp
    ON s.stateID = locgrp.stateID

如果某些地点被拆分为不同州的地区,那么您的设计似乎没问题。使用此:

SELECT 
    STATES.name    AS state
  , LOCATIONS.name AS location
  , AREAS.name     AS area
  , locgrp.locCnt  AS locationsInState 
FROM STATES
  LEFT JOIN AREAS
    ON STATES.stateID = AREAS.stateID
  LEFT JOIN LOCATIONS
    ON AREAS.locID = LOCATIONS.locID
  LEFT JOIN 
    ( SELECT stateID
           , COUNT(DISTINCT locID) AS locCnt
      FROM AREAS
      GROUP BY stateID
    ) AS locgrp
    ON STATES.stateID = locgrp.stateID

或(与您尝试的类似):

SELECT 
    STATES.name    AS state
  , LOCATIONS.name AS location
  , A.name         AS area
  , ( SELECT COUNT(DISTINCT locID)
      FROM AREAS a2
      WHERE a2.stateID = A.stateID
    )              AS locationsInState 
FROM STATES
  LEFT JOIN AREAS A
    ON STATES.stateID = A.stateID
  LEFT JOIN LOCATIONS
    ON A.locID = LOCATIONS.locID

答案 1 :(得分:1)

SELECT s.state as state, l.name as locname, count( l.locID ) as num, a.name as areaname
FROM areas a
JOIN locations l ON a.locID = l.locID
JOIN states s ON s.stateID = a.stateID
GROUP BY l.locID, s.stateID

将提供输出:

state       locname   locs  areaname
Florida     Orlando   2     Area1
Florida     Brevard   1     Area3
New Jersey  North NJ  2     Area4
New Jersey  South NJ  1     Area6
California  B Hills   1     Area7
California  East LA   1     Area8
California  SanFran   1     Area9

但是,如果您需要列出的每个区域都使用查询:

SELECT s.state AS state, 
       l.name AS locname, 
       ( SELECT count( a1.name ) FROM areas a1
         WHERE a1.locID = a.locID
         AND a1.stateID = a.stateID ) AS locs,
       a.name
FROM areas a
JOIN locations l ON a.locID = l.locID
JOIN states s ON s.stateID = a.stateID

将为您提供输出:

state       locname   locs  areaname
Florida     Orlando   2     Area1
Florida     Orlando   2     Area2
Florida     Brevard   1     Area3
New Jersey  North NJ  2     Area4
New Jersey  North NJ  2     Area5
New Jersey  South NJ  1     Area6
California  B Hills   1     Area7
California  East LA   1     Area8
California  SanFran   1     Area9