RedShift GROUP BY常量列导致结果不一致

时间:2017-03-21 00:08:17

标签: sql amazon-redshift

我想知道是否有人可以帮助解释为什么在GROUP BY的常量列上使用VARCHAR而在INTEGER上使用CREATE TABLE test.show_bug AS WITH integers AS ( SELECT 0 AS num UNION SELECT 1 AS num UNION SELECT 2 AS num UNION SELECT 3 AS num UNION SELECT 4 AS num UNION SELECT 5 AS num ) SELECT '2017-03-16' + mod(a.num, 2) AS date_time , CASE mod(b.num, 3) WHEN 0 THEN 'source_a' WHEN 1 THEN 'source_b' WHEN 2 THEN 'source_c' END AS user_source , b.num || a.num || b.num || a.num || b.num AS user_id FROM integers AS a CROSS JOIN integers AS b ; 会给出不同的行为。

这是我最小的工作示例。下表嘲笑了我发现此问题的真实数据:

 date_time  | user_source | user_id
------------+-------------+---------
 2017-03-17 | source_a    | 3113313
 2017-03-17 | source_b    | 4114414
 2017-03-17 | source_b    | 1111111
 2017-03-16 | source_a    | 0000000
 2017-03-16 | source_c    | 2442242
 2017-03-16 | source_c    | 5225525
....
(36 rows)

这看起来像:

COUNT

基本上我希望能够UNION(每天)用户数量,来源数量和每个来源的用户数量。但是,我有两个相同格式的表,我希望app_1将结果放在一起。我可以通过为每个结果添加一个常量列来区分这些结果:app_2SELECT 'app_1' AS app , date_time , COUNT(user_source) , COUNT(DISTINCT user_source) , COUNT(DISTINCT user_id) FROM test.show_bug GROUP BY 1, 2 UNION SELECT 'app_2' AS app , date_time , COUNT(user_source) , COUNT(DISTINCT user_source) , COUNT(DISTINCT user_id) FROM test.show_bug GROUP BY 1, 2

为了示例,我使用相同的模拟表两次,但在实际应用程序中,我有两个不同的表,无论是以下sql应该得到我想要的结果:

   app    |     date_trunc      | count | count1 | count2
----------+---------------------+-------+--------+--------
 app_1    | 2017-03-16 00:00:00 |     2 |      1 |      0
 app_1    | 2017-03-17 00:00:00 |     2 |      1 |      0
 app_1    | 2017-03-19 00:00:00 |     5 |      0 |      1
 app_2    | 2017-03-19 00:00:00 |     7 |      1 |      0
 app_1    | 2017-03-16 00:00:00 |     0 |      1 |      0
....
(112 rows)

这导致

1

这是不正确的,因为我实际期望的是使用整数值2VARCHAR代替app_1app_2获得的结果SELECT 1 AS app , date_time , COUNT(user_source) , COUNT(DISTINCT user_source) , COUNT(DISTINCT user_id) FROM test.show_bug GROUP BY 1, 2 UNION SELECT 2 AS app , date_time , COUNT(user_source) , COUNT(DISTINCT user_source) , COUNT(DISTINCT user_id) FROM test.show_bug GROUP BY 1, 2 ,例如:

   app    |     date_trunc      | count | count1 | count2
----------+---------------------+-------+--------+--------
        1 | 2017-03-16 00:00:00 |   192 |     16 |    192
        1 | 2017-03-17 00:00:00 |   208 |     14 |    208
        1 | 2017-03-18 00:00:00 |   203 |     14 |    203
        1 | 2017-03-19 00:00:00 |   203 |     14 |    203
        1 | 2017-03-20 00:00:00 |    35 |      0 |     35
        2 | 2017-03-16 00:00:00 |   192 |     16 |    192
        2 | 2017-03-17 00:00:00 |   208 |     14 |    208
        2 | 2017-03-18 00:00:00 |   203 |     14 |    203
        2 | 2017-03-19 00:00:00 |   203 |     14 |    203
        2 | 2017-03-20 00:00:00 |    35 |      0 |     35

给了我:

UNION

如果我不使用VARCHAR,也可以看到此效果。

有一些明显的解决方法可以获得我想要的结果,但是这里的根本问题是使用INTEGER常量列而不是out <- strsplit(sentence, "-") last <- out[length(out)] flip <- rev(last) word <- paste(flip, collapse='') 常量的行为似乎存在不直观的差异列。

如果有人能帮我理解这种差异,我将非常感激。

2 个答案:

答案 0 :(得分:3)

我说你在Amazon Redshift中发现了一个真正的错误,或者至少是一个不受欢迎的行为。

我设法将其缩小到:

  • 仅当VARCHAR用作GROUP BY和
  • 之一时
  • 使用多个COUNT(DISTINCT)语句时

因此,这个简单的陈述也会产生太多结果:

SELECT 
    '1',
    COUNT(DISTINCT user_source),
    COUNT(DISTINCT user_id)
FROM show_bug
GROUP BY 1

但这没关系:

SELECT 
    '1'::INTEGER,
    COUNT(DISTINCT user_source),
    COUNT(DISTINCT user_id)
FROM show_bug
GROUP BY 1

删除任何COUNT(DISTINCT)条目也可以使其正常工作。

如果您订阅了AWS Support,我建议您提交错误报告。如果您未订阅支持,可以通过AWS Support论坛提交支持,但它们无法保证响应时间。

答案 1 :(得分:0)

将文字转换为特定类型会更改行为,但仍会产生不一致的结果。使用UNION ALL可以避免模糊某些问题,下面的一些查询会返回更多结果。

使用CHAR获得4行:

SELECT
    'app_1'::CHAR(5) AS app
    , date_time
    , COUNT(user_source)
    , COUNT(DISTINCT user_source)
    , COUNT(DISTINCT user_id)
FROM test.show_bug
GROUP BY 1, 2
UNION
SELECT
    'app_2'::CHAR(5) AS app
    , date_time
    , COUNT(user_source)
    , COUNT(DISTINCT user_source)
    , COUNT(DISTINCT user_id)
FROM test.show_bug
GROUP BY 1, 2

  app  | date_time  | count | count1 | count2
-------+------------+-------+--------+--------
 app_2 | 2017-03-16 |    18 |      3 |     18
 app_1 | 2017-03-17 |    18 |      3 |     18
 app_1 | 2017-03-16 |    18 |      3 |     18
 app_2 | 2017-03-17 |    18 |      3 |     18
(4 rows)

VARCHAR给出了不同的结果:

SELECT
    'app_1'::VARCHAR(10) AS app
    , date_time
    , COUNT(user_source)
    , COUNT(DISTINCT user_source)
    , COUNT(DISTINCT user_id)
FROM test.show_bug
GROUP BY 1, 2
UNION
SELECT
    'app_2'::VARCHAR(10) AS app
    , date_time
    , COUNT(user_source)
    , COUNT(DISTINCT user_source)
    , COUNT(DISTINCT user_id)
FROM test.show_bug
GROUP BY 1, 2

  app  | date_time  | count | count1 | count2
-------+------------+-------+--------+--------
 app_1 | 2017-03-16 |     3 |      1 |      0
 app_1 | 2017-03-17 |     3 |      1 |      0
 app_2 | 2017-03-17 |     0 |      1 |      0
 app_2 | 2017-03-16 |     3 |      1 |      0
 app_2 | 2017-03-17 |     0 |      0 |      1
 app_1 | 2017-03-16 |     0 |      0 |      1
 app_2 | 2017-03-16 |     0 |      0 |      1
 app_1 | 2017-03-17 |     0 |      1 |      0
 app_2 | 2017-03-16 |     0 |      1 |      0
 app_1 | 2017-03-16 |     0 |      1 |      0
 app_1 | 2017-03-17 |     0 |      0 |      1
 app_2 | 2017-03-17 |     3 |      1 |      0
(12 rows)

使用INT会得到与上面的CHAR相同的结果。

哇,这太可怕了。现在我必须查看所有使用这样的文字的查询来对结果集进行分类。