MySQL: получение количества строк на основе коррелированного подзапроса подзапроса - PullRequest
0 голосов
/ 28 апреля 2011

Прошу прощения, если на этот вопрос ответили еще где, я выдернул свои волосы в поисках, но пока ничего не нашел.

У меня есть следующие таблицы:

    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;

Конечно, это не удается из-за отсутствиялюбой STATES.stateID в подзапросе 1 для подзапроса 2 для ссылки.Я попытался передать stateID вместе с JOIN в таблицу в подзапросе 1, а также JOIN в подзапросе 2 вместо того, чтобы пытаться ссылаться на нее в операторе WHERE.Это также не помогает, учитывая, что весь подзапрос 2 является частью оператора WHERE для подзапроса 1 ...

Я также пытался изолировать запросы, чтобы получить только AREAS.stateID и COUNT(locations in state), но длябезрезультатно, я продолжаю получать количество областей в штате, а не количество местоположений:

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

Бросок DISTINCT в COUNT() приближает меня, но некоторые значения по-прежнему отключены, не уверен, откуда берутся цифры, так как они не соответствуют количеству локаций для всех случаев, но большинство из них ...

Ответы [ 2 ]

1 голос
/ 28 апреля 2011
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
1 голос
/ 28 апреля 2011

Если я правильно понимаю:

  • каждое государство имеет много мест (отношение 1-ко-многим)

и

  • каждоеМестоположение имеет много областей (отношение 1-ко-многим)

Итак, в таблице Location должен быть stateID в качестве внешнего ключа к таблице 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
...