Вопрос SQL для начинающих: арифметика с несколькими результатами COUNT (*) - PullRequest
9 голосов
/ 29 мая 2010

Продолжая придерживаться духа использования Stack Exchange Data Explorer для изучения SQL (см .: Можем ли мы стать нашим «северным ветром» для обучения SQL / базам данных? ), я решил попробовать написать запрос, чтобы ответить на простой вопрос (по мета): Какой процент пользователей stackoverflow имеет более 10000 представителей? .

Вот что я сделал:

Запрос # 1

SELECT COUNT(*)
FROM Users
WHERE
  Users.Reputation >= 10000

Результат:

556

Запрос # 2

SELECT COUNT(*)
FROM
  USERS

Результат:

227691

Теперь, как мне собрать их в один запрос? Как называется этот запрос? Что мне нужно написать, чтобы я мог получить, скажем, трехстрочный результат из одной строки, например:

556     227691      0,00244190592

Ответы [ 6 ]

11 голосов
/ 29 мая 2010

Вы можете использовать Общее табличное выражение (CTE) :

WITH c1 AS (
    SELECT COUNT(*) AS cnt
    FROM Users
    WHERE Users.Reputation >= 10000
), c2 AS (
    SELECT COUNT(*) AS cnt
    FROM Users
)
SELECT c1.cnt, c2.cnt, CAST(c1.cnt AS FLOAT) / c2.cnt
FROM c1, c2
3 голосов
/ 31 мая 2010

Для подобных запросов, когда я делаю несколько подсчетов для одной таблицы на основе разных критериев, мне нравится использовать SUM и CASE:

SELECT
    UsersCount.[10K],
    UsersCount.[All],
    (CAST(UsersCount.[10K] AS FLOAT) / UsersCount.[All]) AS [Ratio]
FROM
    (SELECT
         SUM(CASE
               WHEN Users.Reputation >= 10000 THEN 1
               ELSE 0
             END) AS [10K],
         COUNT(*) AS [All]
     FROM Users) AS UsersCount

( результаты запроса )

Преимущество состоит в том, что вы сканируете таблицу пользователей только один раз, что может быть значительно быстрее.

3 голосов
/ 29 мая 2010

Благодаря другим ответам здесь, я написал следующие запросы, все из которых работают на SEDE:

«Встроенный вид»

SELECT *, CAST([10K] AS FLOAT)/[All] AS [Ratio]
FROM (
   SELECT
    (SELECT COUNT(*) FROM Users) AS [All],
    (SELECT COUNT(*) FROM Users Where Reputation >= 10000) AS [10K]
) AS UsersCount

( См. Результат запроса )


Переменные

DECLARE @numAll FLOAT
DECLARE @num10kers FLOAT

SET @numAll = (SELECT COUNT(*) FROM Users)
SET @num10kers = (SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000);

SELECT  @num10kers AS [10K], @numAll AS [All], @num10Kers/@numAll AS [Ratio]

( См. Результат запроса )

Ссылки


Общее табличное выражение

WITH Users10K AS ( 
    SELECT COUNT(*) AS Count
    FROM Users
    WHERE Users.Reputation >= 10000
), UsersAll AS (
    SELECT COUNT(*) As Count
    FROM Users
)
SELECT
    Users10K.Count AS [10K],
    UsersAll.Count AS [All],
    CAST(Users10K.Count AS FLOAT) / UsersAll.Count AS [Ratio]
FROM Users10K, UsersAll

( См. Результат запроса )

Ссылки

3 голосов
/ 29 мая 2010

Помимо с использованием CTE , в этом случае вы также могли бы сделать:

SELECT CAST((SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000) AS float)  /
       (SELECT COUNT(*) FROM USERS) * 100  AS Percentage​

Бросок в формате с плавающей точкой должен был вызвать деление с плавающей запятой, потому что при целочисленном делении 556/227691 даст 0.

2 голосов
/ 29 мая 2010

Использование переменных в MySQL:

SELECT @a:=(SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000),
       @b:=(SELECT COUNT(*) FROM Users),
       IF(@b > 0, @a/@b, "--invalid--")
FROM Users
LIMIT 0,1
2 голосов
/ 29 мая 2010
WITH tmp as (
SELECT COUNT(ID) AS repCount, (SELECT COUNT(ID) FROM Users ) AS totalCount
FROM Users
WHERE Users.Reputation > 10000
)
SELECT tmp.repCount, tmp.totalCount, (cast(tmp.repCount as decimal(10,2))/tmp.TotalCount) * 100 AS Percentage
FROM tmp

ОБНОВЛЕНО: без с

SELECT COUNT(ID) AS repCount, (SELECT COUNT(ID) FROM Users ) AS totalCount, 
    (CAST((SELECT COUNT(ID) FROM Users WHERE Users.Reputation > 10000) AS DECIMAL(10,2)) /
        (SELECT COUNT(ID) FROM Users )) * 100 AS Persantage
FROM Users
...