如何基于多个唯一列选择数据而不在结果集中的其余列上应用聚合函数

Posted

技术标签:

【中文标题】如何基于多个唯一列选择数据而不在结果集中的其余列上应用聚合函数【英文标题】:How to select data based on Multiple Unique Columns without applying aggregate functions on rest of columns in resultset 【发布时间】:2016-11-02 18:23:33 【问题描述】:

这可能看起来重复,但我找不到符合我要求的答案。参考here,但它并不完全相同,答案不适用于我。因此问。

SELECT tab1.col1, tab1.col2, tab1.col3, tab2.col3, tab2.col4 
from 
     (SELECT col1, col2, col3 
      FROM table1 
      GROUP BY col1, col2, col3) AS tab1
JOIN tab2 
  ON tab1.col1 = tab2.col1 
 AND tab1.col2 = tab2.col2
GROUP BY tab1.col1, tab1.col2, tab1.col3, tab2.col3, tab2.col4

示例数据:

Table1                          Tab2            
col1  | col2   |   col3         col1  |  col2 | col3  |  col4
=======================         =============================
page1   image1  referer1        page1   image1  150      75
page1   image1  referer1        page1   image1  120      85
page2   image2  referer2        page2   image2  200      400
page1   image1  referer1        page1   image1  750     1024
page2   image2  referer2        page2   image2  450      575
page1   image1  referer1        page1   image1  600      900

预期输出:

tab1.col1  |  tab1.col2  |  tab1.col3  |  tab2.col3  |   tab2.col4
==================================================================
  page1       image1        referer1        600            900
  page2       image2        referer2        200            400

这里最后一个 group by 返回唯一行,但所有 tab1 cols 都在重复,这是我不想要的,在这种情况下,记录仅在 tab2.col1 和 tab2.col2 上有所不同。现在的要求是我希望 tab1.col1、tab1.col2、tab1.col3 是唯一的,并且对于来自 tab2 的那些列只有一对相应的 tab2.col1 和 tab2.col2。 现在我无法从第二组 by 中删除 tab2.col1、tab2.col2 并应用最小或最大聚合函数,因为在这种情况下,我不会得到映射到 tab2.col2 值的 tab2.col1 值特定记录。

注意:我使用 Amazon Redshift 作为数据库。子查询很重要,因为它实际上是由 3 个表连接产生的复杂结果集,如果我将这 3 个表的连接直接与 tab2 一起使用,那么查询将永远运行。为了这个问题的简单起见,假设子查询从 table1 返回 col1、col2、col3。 Tab2 和 tab1 是巨大的表:D ...子查询大大提高了性能(减少了 20 分钟到 ~2 分钟)。

【问题讨论】:

您的子查询没有什么复杂的。并且查询本身似乎很不清楚。尝试设置 sqlfiddle 并用您需要的一些数据集和预期结果来解释您的目标。 请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。 向我们展示示例数据和预期输出。 How to create a Minimal, Complete, and Verifiable example 您的示例抓取每个组中的“最后”行。有关相关主题,请参阅 Groupwise max。 MariaDB 10.2 的窗口化功能可能也会有所帮助。 我提供的链接适用于常规 mysql 【参考方案1】:

如果以下结果是您的要求,

tab1.col1  |  tab1.col2  |  tab1.col3  |  tab2.col3  |   tab2.col4
==================================================================
  page1       image1        referer1        120            85
  page2       image2        referer2        200            400

那么你可以使用下面的 redshift sql 查询来实现它

SELECT tab1.col1, tab1.col2, tab1.col3, tab2.col3, tab2.col4
FROM
  (SELECT col1, col2, col3
   FROM table1
   GROUP BY col1, col2, col3) AS tab1
JOIN
  (SELECT col1, col2, col3, col4
   FROM
     (SELECT col1, col2, col3, col4, ROW_NUMBER() OVER(PARTITION BY col1, col2 ORDER BY col3 ASC, col4 ASC) row_num
      FROM table2) tab2
   WHERE row_num = 1) tab2 ON tab1.col1 = tab2.col1
      AND tab1.col2 = tab2.col2

上述sql语句中的key为“ROW_NUMBER() OVER(PARTITION BY col1, col2 ORDER BY col3 ASC, col4 ASC)”。这将为您提供 tab2.col3 的最小值tab2.col4 的最小值。如果您需要 ma​​x 值,则将顺序更改为 DESC

希望这能解决您的问题。

你也可以查看我写的结果集here

【讨论】:

以上是关于如何基于多个唯一列选择数据而不在结果集中的其余列上应用聚合函数的主要内容,如果未能解决你的问题,请参考以下文章

如果要在T-SQL中的多个列上中断数据,请添加Quartiles

SQLite 表约束 - 在多个列上唯一

Oracle11G_索引

在 MySQL Workbench EER 图中的多个列上创建唯一约束

在 DataGridView 的同一列上添加多个数据源

从 Spark DataSet 中的单个列派生多个列并在新列上分组 [重复]