“where-in”子句中的强制条件匹配

Mandatory condition matching in ´where-in´ clause

考虑一个简单的 where 子句

select * from table_abc where col_a in (1,2,3)

我知道现在的情况

我的问题是我们是否可以针对

的条件执行查询

编辑:正如评论中所指出的,我忘记添加 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);