“where-in”子句中的强制条件匹配
Mandatory condition matching in ´where-in´ clause
考虑一个简单的 where 子句
select * from table_abc where col_a in (1,2,3)
我知道现在的情况
- 如果没有1,2,3,我将得不到任何结果
- 如果 1,2,3 存在,我将得到与 1,2,3 相关联的所有结果
- 如果 1 存在而 2,3 不存在,我将只得到与 1 相关的结果。
我的问题是我们是否可以针对
的条件执行查询
如果 1 存在而 2,3 不存在,我仍然应该得到与 1,2,3
相关的所有结果
但是,如果没有1,2,3,我将得不到任何结果
换句话说,我可以将 where-in 子句中的特定值设置为强制性的吗?我们如何更改当前查询?
编辑:正如评论中所指出的,我忘记添加 table 结构。我最好也解释一下用例。
Table 1:管理员
ID admin_id
-------------
1 001
2 002
Table 2:事件
ID event_id
-------------
1 110
2 220
Table 3 : Admins_Events
admin_id event_id
-------------
001 110
001 220
002 220
现在,作为过滤的一部分,假设我有查询
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
LEFT JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
LEFT JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
WHERE (events.event_id IN (110) AND admins.admin_id IN (001))
目前,我得到的结果是
admin_id event_id
-------------
001 110
我想要的是
admin_id event_id
-------------
001 110
001 220
即使我没有在 where-in 子句中传递它,我仍然必须显示与管理员相关的其他事件。我想每次都传递所有 event_id 并匹配强制性 event_id 并匹配剩余的 event_id 以防发现强制性 event_id。
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
LEFT JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
LEFT JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
WHERE (events.event_id IN (mandatory[110], 220) AND admins.admin_id IN (001))
如何更改查询?
听起来在您的示例中您想要所有与事件 110 关联的管理员关联的事件。在 Mysql 中,我将使用以下查询执行此操作,该查询将管理员加入事件两次:一次到过滤您需要的事件,并过滤一次以获取所有其他事件。
但是,在您的示例中,您根本不需要查询中的管理员 table,因为您只需要管理员 ID,您可以直接从 admins_events table。我把它留在里面,以防你的真实 "admins" table 也有你想要的其他属性(名称、位置等),这些属性在 admins_events 连接 table 中不可用。
具体查询为:
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
JOIN "admins_events" AS "specific_admins_events" ON "specific_admins_events"."admin_id" = "admins"."admin_id"
JOIN "events" AS "specific_events" ON "specific_events"."event_id" = "specific_admins_events"."event_id"
WHERE (specific_events.event_id IN (110))
在 WHERE
子句中使用 EXISTS
添加另一个条件:
SELECT a.admin_id, e.event_id
FROM Admins a
LEFT JOIN Admins_Events ae ON ae.admin_id = a.admin_id
LEFT JOIN Events e ON e.event_id = ae.event_id
WHERE (e.event_id IN (110, 220) AND a.admin_id IN (001))
AND EXISTS (
SELECT 1 FROM Admins_Events
WHERE event_id = 110 AND admin_id = a.admin_id
)
参见demo。
结果:
| admin_id | event_id |
| -------- | -------- |
| 1 | 110 |
| 1 | 220 |
首先,您只需要 admin_events
table.
然后方法使用window函数:
SELECT ae.*
FROM (SELECT ae.*,
SUM(CASE WHEN ae.event_id IN (110) THEN 1 ELSE 0 END) OVER (PARTITION BY ae.admin_id) as num_110
FROM admins_events ae
) ae
WHERE ae.admin_id IN ('001') AND -- assume this is a string
num_110 > 0 AND
ae.event_id IN (110, 220);
考虑一个简单的 where 子句
select * from table_abc where col_a in (1,2,3)
我知道现在的情况
- 如果没有1,2,3,我将得不到任何结果
- 如果 1,2,3 存在,我将得到与 1,2,3 相关联的所有结果
- 如果 1 存在而 2,3 不存在,我将只得到与 1 相关的结果。
我的问题是我们是否可以针对
的条件执行查询如果 1 存在而 2,3 不存在,我仍然应该得到与 1,2,3
相关的所有结果但是,如果没有1,2,3,我将得不到任何结果
换句话说,我可以将 where-in 子句中的特定值设置为强制性的吗?我们如何更改当前查询?
编辑:正如评论中所指出的,我忘记添加 table 结构。我最好也解释一下用例。
Table 1:管理员
ID admin_id
-------------
1 001
2 002
Table 2:事件
ID event_id
-------------
1 110
2 220
Table 3 : Admins_Events
admin_id event_id
-------------
001 110
001 220
002 220
现在,作为过滤的一部分,假设我有查询
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
LEFT JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
LEFT JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
WHERE (events.event_id IN (110) AND admins.admin_id IN (001))
目前,我得到的结果是
admin_id event_id
-------------
001 110
我想要的是
admin_id event_id
-------------
001 110
001 220
即使我没有在 where-in 子句中传递它,我仍然必须显示与管理员相关的其他事件。我想每次都传递所有 event_id 并匹配强制性 event_id 并匹配剩余的 event_id 以防发现强制性 event_id。
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
LEFT JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
LEFT JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
WHERE (events.event_id IN (mandatory[110], 220) AND admins.admin_id IN (001))
如何更改查询?
听起来在您的示例中您想要所有与事件 110 关联的管理员关联的事件。在 Mysql 中,我将使用以下查询执行此操作,该查询将管理员加入事件两次:一次到过滤您需要的事件,并过滤一次以获取所有其他事件。
但是,在您的示例中,您根本不需要查询中的管理员 table,因为您只需要管理员 ID,您可以直接从 admins_events table。我把它留在里面,以防你的真实 "admins" table 也有你想要的其他属性(名称、位置等),这些属性在 admins_events 连接 table 中不可用。
具体查询为:
SELECT "admins"."admin_id", "events"."event_id" FROM "admins"
JOIN "admins_events" ON "admins_events"."admin_id" = "admins"."admin_id"
JOIN "events" ON "events"."event_id" = "admins_events"."event_id"
JOIN "admins_events" AS "specific_admins_events" ON "specific_admins_events"."admin_id" = "admins"."admin_id"
JOIN "events" AS "specific_events" ON "specific_events"."event_id" = "specific_admins_events"."event_id"
WHERE (specific_events.event_id IN (110))
在 WHERE
子句中使用 EXISTS
添加另一个条件:
SELECT a.admin_id, e.event_id
FROM Admins a
LEFT JOIN Admins_Events ae ON ae.admin_id = a.admin_id
LEFT JOIN Events e ON e.event_id = ae.event_id
WHERE (e.event_id IN (110, 220) AND a.admin_id IN (001))
AND EXISTS (
SELECT 1 FROM Admins_Events
WHERE event_id = 110 AND admin_id = a.admin_id
)
参见demo。
结果:
| admin_id | event_id |
| -------- | -------- |
| 1 | 110 |
| 1 | 220 |
首先,您只需要 admin_events
table.
然后方法使用window函数:
SELECT ae.*
FROM (SELECT ae.*,
SUM(CASE WHEN ae.event_id IN (110) THEN 1 ELSE 0 END) OVER (PARTITION BY ae.admin_id) as num_110
FROM admins_events ae
) ae
WHERE ae.admin_id IN ('001') AND -- assume this is a string
num_110 > 0 AND
ae.event_id IN (110, 220);