根据连接中使用的联合列获取正确的记录
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 |
希望我的解释足够清楚。
【问题讨论】:
请编辑您的问题,在查询中为您的id
、value
和discount
列设置别名。这些列属于哪个表?
您在查询的第二部分中错过了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 个CTE
s,然后使用 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
。完全选择真的又大又难,所以用WITH
和left outer join
包完成了一个小时。但是,仍然感谢您的解决方案!
@Viktor CTE 不会给要求增加任何负担。相反,第二个查询中的 EXISTS 将快速返回,如果第一个查询中有 1,则第二个 CTE 也将快速返回而没有任何结果。以上是关于根据连接中使用的联合列获取正确的记录的主要内容,如果未能解决你的问题,请参考以下文章