首页 > 解决方案 > 获取具有多个条件的行

问题描述

下面是我的 Postgres 表:

桌子:

+------+-----------------+---------+
| sku  | properties      | value   |
|------+-----------------+---------|
| 1    | Family_ID       | 21      |
| 1    | Class_ID        | 21      |
| 2    | Family_ID       | 20      |
| 2    | Class_ID        | 21      |
| 3    | Family_ID       | 21      |
| 3    | Class_ID        | 21      |
+------+-----------------+---------+
  1. 如何查询是否要获取Family_IDandClass_ID所在的数据21

预期返回值:

+------+-----------------+---------+
| sku  | properties      | value   |
|------+-----------------+---------|
| 1    | Family_ID       | 21      |
| 1    | Class_ID        | 21      |
| 3    | Family_ID       | 21      |
| 3    | Class_ID        | 21      |
+------+-----------------+---------+
  1. 如何查询是否要获取Family_IDis20Class_IDis的数据21

预期返回值:

+------+-----------------+---------+
| sku  | properties      | value   |
|------+-----------------+---------|
| 2    | Family_ID       | 20      |
| 2    | Class_ID        | 21      |
+------+-----------------+---------+

标签: sqlpostgresql

解决方案


要跨行进行操作,您需要进行分组,但这里最简单的事情(假设您似乎想要这个主题的更多变体)可能是旋转您的数据:

WITH x as(
 SELECT f.sku, c.value as class_value, f.value as family_value
 FROM
  (select sku, value FROM table WHERE properties = 'family_id') f
  INNER JOIN
  (select sku, value FROM table WHERE properties = 'class_id') c
  ON f.sku = c.sku
)

您现在可以像往常一样使用 WHERE 子句:

SELECT * FROM x WHERE family_value = 20 and class_value = 21

如果您需要以列格式返回数据,您可以再次对其进行反透视:

SELECT
  sku,
  'family_id' as properties,
  family_value as value
FROM 
  x

UNION ALL

SELECT
  sku,
  'class_id' as properties,
  class_value as value
FROM 
  x

但是,仅使用旋转形式的数据可能会更容易。

我自己不一定会这样做,但是如果您习惯于定期加入、联合和其他类似的“典型”数据库操作,那么理解这种旋转形式会容易得多,所以我推荐您这样做,因为您可能会发现更容易维护和扩展。进行数据透视的条件聚合可能更有效,但维护起来更复杂:

WITH X as (
  SELECT
    sku,
    MAX(CASE WHEN properties = 'Family_ID' THEN value END) as family_value,
    MAX(CASE WHEN properties = 'Class_ID' THEN value END) as class_value
  FROM
    table
  GROUP BY sku
)

CASE WHENvalue根据properties值将 s 分布在列中。group by/max 然后折叠删除空值的行,为您留下唯一的 sku 和命名列中的值,具体取决于它们是什么类型的值


推荐阅读