使用 OR 和标签连接多个列上的两个表

Posted

技术标签:

【中文标题】使用 OR 和标签连接多个列上的两个表【英文标题】:Join two tables on multiple columns with OR and label 【发布时间】:2021-12-26 14:24:52 【问题描述】:

我有两个表,如下所示:

orderID customerID
1 1001
2 1002
3 1003
4 1003

另一个是这样的:

userID Service1FirstOrderID Serice2FirstOrderID Service3FirstOrderID
1001 null 1 null
1002 2 null null
1003 3 null 4

现在我想加入这两个表,以便我可以获取每个已购买的带有ServiceID 的客户 ID。

UserID Service
1001 2
1002 1
1003 1
1003 3

任何帮助将不胜感激。

【问题讨论】:

您真正使用的是哪个 DBMS? mysql (x) 还是 MySQL?只标记您真正使用的那个,仅此而已。 Edit 这样做的问题。 你是对的。我正在使用 SQL Server Edit 问题并解释结果背后的逻辑。 看起来这根本不是一个连接。它似乎纯粹是第二个表的条件逆透视,您可以使用CROSS APPLY (SELECT 1 WHERE Service1FirstOrderID IS NOT NULL UNION ALL SELECT 2 WHERE Service2FirstOrderID IS NOT NULL... 执行此操作,例如dbfiddle.uk/…。虽然为什么你首先有一个如此糟糕的非规范化结构是一个不同的问题 这行不通,因为还有一些其他列和条件已应用于第一个表,我应该计算 customerID,所以我必须加入这两个表,以便我可以计算客户每个服务 【参考方案1】:

可以加入IN

SELECT
  so.userID
, CASE 
  WHEN o.OrderID = so.Service1FirstOrderID THEN 1
  WHEN o.OrderID = so.Service2FirstOrderID THEN 2
  WHEN o.OrderID = so.Service3FirstOrderID THEN 3
  END AS Service
FROM Orders o
INNER JOIN ServiceOrders so
  ON so.userID = o.customerID
 AND o.OrderID IN (so.Service1FirstOrderID, so.Service2FirstOrderID, so.Service3FirstOrderID)
ORDER BY o.customerID;
userID Service
1001 2
1002 1
1003 1
1003 3

dbfiddle here

上的演示

【讨论】:

【参考方案2】:

您有一个高度非规范化的表结构,但看起来这根本不是一个连接。

这似乎纯粹是第二个表的条件逆透视,您可以使用CROSS APPLY 来完成

SELECT
  t2.UserId,
  v.*
FROM table2 t2
CROSS APPLY (
    SELECT 1
    WHERE Service1FirstOrderID IS NOT NULL
    UNION ALL
    SELECT 2
    WHERE Service2FirstOrderID IS NOT NULL
    UNION ALL
    SELECT 3
    WHERE Service3FirstOrderID IS NOT NULL
) v(Service);

db<>fiddle

【讨论】:

【参考方案3】:

您可以使用 CTE 实现此目的。

;WITH CTE_ServiceOrder as
(
SELECT UserId, 1 AS ServiceId, Service1FirstOrderID as orderId
from ServiceOrders
where Service1FirstOrderId is not null
union all
SELECT UserId, 2,  Service2FirstOrderID as orderId
from ServiceOrders
where Service2FirstOrderId is not null
union all
SELECT UserId, 3, Service3FirstOrderID as orderId
from ServiceOrders
where Service3FirstOrderId is not null
)
SELECT o.customerID, s.ServiceId FROM CTE_ServiceOrder as s
INNER JOIN Orders as o
on o.orderID = s.orderid
order by o.customerID

感谢@Lukstorms 创建脚本。

您可以参考dbfiddle

【讨论】:

以上是关于使用 OR 和标签连接多个列上的两个表的主要内容,如果未能解决你的问题,请参考以下文章

非聚集索引 - 几乎相同需求的一个或两个索引(两个表之间的连接)?

基于另一列的最大值的列上的 SQL 内连接 [重复]

Pyspark 与 AWS Glue 在多个列上加入创建重复项

具有别名的同一列上的多个连接

HQL 无法在公共外键列上连接两个表

在其他两个表的列上连接一列的最佳方法