Вычислить процент или строки, которые не равны NULL, для каждого столбца в таблице, сгруппированной по другому столбцу. - PullRequest
0 голосов
/ 08 января 2020

У меня есть обычная таблица [customer_table] с некоторыми нулевыми значениями, которая выглядит следующим образом

id | customer | country | col0 | col1 | col2 |
==============================================
1  | foo      | USA     | NULL | foo  | bar  | 
2  | bar      | USA     | foo  | NULL | foo  | 
3  | foo2     | CANADA  | bar  | col1 | NULL | 
4  | bar2     | GERMANY | foo  | NULL | bar  | 
5  | bar3     | CANADA  | foo  | foo  | bar  | 
6  | bar4     | UK      | bar  | foo  | bar  | 
7  | bar5     | UK      | bar  | bar  | bar  | 

И я хочу вычислить процент ненулевых значений для каждого столбца, сгруппированного по стране

country | col0%  | col1% | col2% |
==================================
USA     | 50%    | 50%  | 100%   |
GERMANY | 100%   | 0%   | 100%   |
CANADA  | 100%   | 100% | 50%    |
UK      | 100%   | 100% | 100%   |

Это то, к чему я пытался

select TOTAL.[country],
[count_col0]*100/[count_total] as [col0%],
[count_col1]*100/[count_total] as [col1%]
from (
    (select [country], COUNT(*) as [count_total] from [customer_table]
     where [country] <> '' group by [country]) TOTAL
    left join
     (select [country], COUNT(*) as [count_col0] from [customer_table] 
     where [country] <> '' and [col0] <> '' group by [country]) T_COL0
     on T_COL0.[country] = TOTAL.[country]
    left join 
     (select [country], COUNT(*) as [count_col1] from [customer_table] 
     where [country] <> '' and [col1] <> '' group by [country]) T_COL1
     on T_COL1.[country] = TOTAL.[country]
)

Это работает, но у меня много столбцов, и я не думаю, что это хорошее решение

Ответы [ 3 ]

2 голосов
/ 08 января 2020

Просто используйте агрегацию. Самый простой метод:

select country,
       count(col1) * 1.0 / count(*),
       count(col2) * 1.0 / count(*),
       count(col3) * 1.0 / count(*)
from customertable
group by country
0 голосов
/ 08 января 2020

Здесь вы ищете шаблон COUNT (DISTINCT xxx) / COUNT (*).

Теперь, когда у вас есть много столбцов для покрытия, вы можете найти их в системной таблице INFORMATION_SCHEMA.COLUMNS и сгенерируйте свой запрос, который вы хотите выполнить следующим образом:

SELECT
  'SELECT country'
UNION ALL
SELECT
      CONCAT(', (100 * COUNT(DISTINCT ', COLUMN_NAME, ')) / COUNT(*) AS [', COLUMN_NAME, '%]')
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'customer_table'
      AND TABLE_SCHEMA = 'dbo'
      AND COLUMN_NAME NOT IN ('id', 'customer', 'country')
UNION ALL
SELECT
  'FROM dbo.customer_table GROUP BY country;'

Что приведет к:

SELECT country
, (100 * COUNT(DISTINCT col0)) / COUNT(*) AS [col0%]
, (100 * COUNT(DISTINCT col1)) / COUNT(*) AS [col1%]
, (100 * COUNT(DISTINCT col2)) / COUNT(*) AS [col2%]
FROM dbo.customer_table GROUP BY country;
0 голосов
/ 08 января 2020
DECLARE @customertable TABLE (country NVARCHAR(100), col1 BIGINT, col2 BIGINT, col3 BIGINT)

INSERT INTO @customertable 
(country, col1, col2, col3)
    VALUES 
    (N'USA', 0, null, 0)
    ,(N'USA', 0, null, 0)
    ,(N'USA', null, null, 0)
    ,(N'USA', 0, 0, null)
    , (N'CA', 0, null, 0)
    ,(N'CA', 0, null, 0)
    ,(N'CA', null, null, 0)
    ,(N'CA', 0, 0, null)
;WITH DistinctCountries AS (
SELECT DISTINCT Country
FROM @customertable
)

SELECT Country
, col1/(total*1.0) as [col1pct]
, col2/(total*1.0) as [col2pct]
, col3/(total*1.0) as [col3pct]
FROM DistinctCountries AS DistinctCountries
OUTER APPLY (
SELECT 
  SUM(CASE WHEN col1 IS NULL THEN 0 ELSE 1 END) col1
  ,SUM(CASE WHEN col2 IS NULL THEN 0 ELSE 1 END) col2
  ,SUM(CASE WHEN col3 IS NULL THEN 0 ELSE 1 END) col3
  ,COUNT(1) as Total
FROM @customertable AS CountApply
WHERE CountApply.Country = DistinctCountries.Country
)MainCount

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

, если у вас тонна столбцов, вероятно, лучше всего создать динамический c SQL запрос для автоматического создайте каждый CASE и токенизируйте его .. или .. динамический c сводный запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...