根据连接中使用的联合列获取正确的记录

Posted

技术标签:

【中文标题】根据连接中使用的联合列获取正确的记录【英文标题】:Get correct records based on column from union which are used in join 【发布时间】:2020-02-27 08:57:06 【问题描述】:

此选择在包中用作left outer join

 SELECT * (SELECT db1.id, db2.value, db1.discount, 2 AS attr_number FROM database1 db1
      JOIN database2 db2 ON db2.db1_id = db1.id
    WHERE db2.value = 1
    UNION
    SELECT db1.id, db4.value, db1.discount, 1 AS attr_number FROM database1 db1
      JOIN database4 db4 ON db4.db1_id = db1.id
    WHERE db4.value = 1) WHERE id = 225

他把这些记录还给我:

|ID           |VALUE             |DISCOUNT          |ATTR_NUMBER       |
|-------------|------------------|------------------|------------------|
|225          |1                 |50                |2                 |
|225          |1                 |50                |2                 |
|225          |1                 |40                |1                 |
|225          |1                 |40                |1                 |
|225          |1                 |40                |1                 |

所以我需要考虑attr_number 行并根据该字段获取记录。

如您所见,attr_number 行值可能只有 1 或 2。

在这个例子中,两个值都存在的记录,在这种情况下我们只需要返回attr_number = 1的位置(因为它存在),所以这是一个他应该返回的例子:

|ID           |VALUE             |DISCOUNT          |ATTR_NUMBER       |
|-------------|------------------|------------------|------------------|
|225          |1                 |40                |1                 |
|225          |1                 |40                |1                 |
|225          |1                 |40                |1                 |

如您所见,他“删除”了 attr_number = 2 的记录,只返回 1 的位置。

在其他情况下,如果选择不返回attr_number = 1 的记录,他返回所有其他记录,在这种情况下它将是attr_number = 2 的位置。这是他在这种情况下应该返回的示例:

|ID           |VALUE             |DISCOUNT          |ATTR_NUMBER       |
|-------------|------------------|------------------|------------------|
|225          |1                 |50                |2                 |
|225          |1                 |50                |2                 |

希望我的解释足够清楚。

【问题讨论】:

请编辑您的问题,在查询中为您的idvaluediscount 列设置别名。这些列属于哪个表? 您在查询的第二部分中错过了WHERE VALUE = 1 - 是来自 db1 还是 db4?如果是后者,则不需要,因为您将其包含在连接条件中。 @Boneist 对不起!现在它应该看起来不错。 如果您可以为 db1、db2 和 db4 表添加数据,那也会很有帮助。很抱歉将更新请求串起来;这不是故意的! @Boneist 一切都很好,但不幸的是我不能,因为这些值不是必需的。如果您要求它检查数据是否相等,那么是的,它们是。这个选择只是一个示例,所以我只是想确保我了解如何制作这个魔法:) 【参考方案1】:

您可以使用RANK 对结果进行排名,并且只保留最好的行(即attr_number 较低的行)。

select db1.id, 1 as value, db1.discount, dbx.attr_number
from database1 db1
join
(
  select db1_id, attr_number, rank() over (order by attr_number) as rn
  from
  (
    select db1_id, 2 as attr_number from database2 db2 where value = 1
    union all
    select db1_id, 1 as attr_number from database4 db4 where value = 1
  )
) dbx on dbx.db1_id = db1.id and dbx.rn = 1
where db1.id = 225;

【讨论】:

很好,会试试!也许您可以建议另一种选择? :)。 attr_number 是一个虚构的列,它不存在于任何表中,只有在 select 中才能理解在 wwitch 步骤中添加了记录(这是以防万一你错过了)。 如您所见,attr_number 在我的查询中也是一个虚构的列 :-) 至于其他选项:先试试这个。然后回来,如果你有问题。【参考方案2】:

为每个联合查询创建 2 个CTEs,然后使用 NOT EXISTS

WITH 
  cte1 AS (
    SELECT db1.id, db4.value, db1.discount, 1 AS attr_number 
    FROM database1 db1 JOIN database4 db4 
    ON db4.db1_id = db1.id
    WHERE id = 225 AND value = 1
  ),
  cte2 AS (
    SELECT db1.id, db2.value, db1.discount, 2 AS attr_number 
    FROM database1 db1 JOIN database2 db2 
    ON db2.db1_id = db1.id
    WHERE id = 225 db2.value = 1
  )
SELECT * FROM cte1
UNION ALL
SELECT * FROM cte2
WHERE NOT EXISTS (SELECT 1 FROM cte1 WHERE attr_number = 1)

【讨论】:

感谢您的留言,但很遗憾在这种情况下我无法使用WITH。完全选择真的又大又难,所以用WITHleft outer join 包完成了一个小时。但是,仍然感谢您的解决方案! @Viktor CTE 不会给要求增加任何负担。相反,第二个查询中的 EXISTS 将快速返回,如果第一个查询中有 1,则第二个 CTE 也将快速返回而没有任何结果。

以上是关于根据连接中使用的联合列获取正确的记录的主要内容,如果未能解决你的问题,请参考以下文章

根据动态列查找匹配记录

根据 Azure 流分析中的时间顺序获取记录的最后一个值

Django ORM:如何根据所有记录中的列获取唯一记录(需要模型对象而不是特定值对象)

Mysql高阶

MySQL增删改查之多表联合查询

如何根据选择的列显示正确的记录