我在 Hive 中有一张桌子,看起来像:
| Name | 1990 | 1991 | 1992 | 1993 | 1994 |
| Rex | 0 | 0 | 1 | 1 | 1 |
| Max | 0 | 0 | 0 | 0 | 1 |
| Phil | 1 | 1 | 1 | 1 | 1 |
我想为每一行获取非零的第一列的名称,例如:
| Name | Column |
| Rex | 1992 |
| Max | 1994 |
| Phil | 1990 |
对于每一行,保证:
- 至少有一列带有“1”;和
- 如果 X 列具有“1”,则对于 Y > X 的每一列,Y 列也将具有“1”。
有一个“微不足道”的解决方案(如下),它假设问题中的保证成立 - 他们今天可能会这样做,但对于不同的查询,谁知道 - 见下面的讨论?
下面的所有代码都可以在 fiddle here上找到。
您的原始表格:
您的数据:
HiveQL 似乎没有 PIVOT 功能,因此您只需要使用老式的手动方式即可。Akina 指出有一个“捷径”:
结果:
但是,对于更长期的解决方案,以及以下示例:
您可能不确定给
1
定(或任何)字段中是否存在值,或您可能希望在很长一段时间内进行查询——比如 1960 年到 2010 年——如果表设计迫使您逐年查询,那么您的 SQL 将是相当可怕的。
因此,您最好使用以下方法:
接着:
并且,检查
SELECT * FROM toradh;
:结果:
因此,您的查询可以这样写:
结果(相同):
您会发现将来编写查询要简单得多,并且您将能够以更简单的方式提出更复杂的数据问题。
例如,想象一下,您的查询不是在 1990 年和 1994 年之间,而是在 1960 年和 2010 年之间 - 它会很大- 这样,它的大小将完全相同 - 只是参数从和到的年份会有所不同!
高瘦而不是矮胖的桌子更好!此外,将来,当您提出此类问题时,能否请您自行设置表格和数据 - 它可以防止代表试图回答的人重复工作,并且它提供了单一的事实来源 - 帮助我们帮你!ps 欢迎来到 dba.se!
几乎同样重要的是,上面的简化查询假设数据是预先知道的——即您已经声明:
然而,除了在最微不足道的情况下,通常不能假设已知值(即使可能相当确定),所以你只需要求助于这样的查询:
结果:
您的查询(鉴于没有数据的先验知识)将如下所示:
同样的结果 - 见小提琴。
总而言之,你最好重构你的模式!将列名作为数据的一部分,您将数据和元数据混合在一起,这绝不是一种好习惯!