从两个表中选择不匹配的列值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从两个表中选择不匹配的列值相关的知识,希望对你有一定的参考价值。

我有两个具有相同列名的表。

例如:

NEEDTOSYNCREQUESTS表

Column Name         Value
----------------------------
ID                  1
LoadId              L1 
ShipmentId          123 
OrderId             NULL
PackageId           P456 
CustomerOTP         99999
ClientOTP           88888

LASTSYNCEDREQUEST表:

Column Name         Value
-------------------------
ID                  1
LoadId              L1 
ShipmentId          NULL
OrderId             1234567
PackageId           P456 
CustomerOTP         44444
ClientOTP           686868

如果您比较上表的列值,您可以看到以下内容:

  1. CustomerOTP和ClientOTP列值不相同。
  2. NEEDTOSYNCREQUESTS中的ShipmentId列具有值,LASTSYNCEDREQUEST表中的ShipmentId列为NULL。
  3. LASTSYNCEDREQUEST表中的OrderId列具有值,并且NEEDTOSYNCREQUESTS表中的ShipmentId列为NULL。

所以,我需要得到以下输出。怎么做到这一点?

OUTPUT

Column Name         Value
---------------------------------
ID                  1
LoadId              NULL 
ShipmentId          123 
OrderId             NULL
PackageId           NULL
CustomerOTP         99999
ClientOTP           88888

条件是,我需要比较上面两个表,并且在与另一个LASTSYNCEDREQUEST表比较时只需要更新的列值NEEDTOSYNCREQUESTS表。注意:两列都具有相同的值或者NEEDTOSYNCREQUESTS表列没有值,那么这些列在输出中应为空。表中的PackageId是相同的(相同)。所以,我需要在输出中将PackageId设为NULL。

请帮我在SQL查询中实现这一点。

提前致谢!

答案

如您所见,所有字段的CASE语句中的3个WHEN中实现了相同的规则。

SELECT A.ID,
CASE WHEN A.LOADID = B.LOADID THEN NULL
     WHEN A.LOADID IS NULL THEN NULL
     WHEN (B.LOADID IS NULL AND A.LOADID IS NOT NULL) OR (A.LOADID IS NOT NULL AND B.LOADID IS NOT NULL) THEN A.LOADID END AS LOADID,
CASE WHEN A.SHIPMENTID = B.SHIPMENTID THEN NULL
     WHEN A.SHIPMENTID IS NULL THEN NULL
     WHEN (B.SHIPMENTID IS NULL AND A.SHIPMENTID IS NOT NULL) OR (A.SHIPMENTID IS NOT NULL AND B.SHIPMENTID IS NOT NULL) THEN A.SHIPMENTID END AS SHIPMENTID,
CASE WHEN A.ORDERID = B.ORDERID THEN NULL
     WHEN A.ORDERID IS NULL THEN NULL
     WHEN (B.ORDERID IS NULL AND A.ORDERID IS NOT NULL) OR (A.ORDERID IS NOT NULL AND B.ORDERID IS NOT NULL) THEN A.ORDERID END AS ORDERID,
CASE WHEN A.PACKAGEID = B.PACKAGEID THEN NULL
     WHEN A.PACKAGEID IS NULL THEN NULL
     WHEN (B.PACKAGEID IS NULL AND A.PACKAGEID IS NOT NULL) OR (A.PACKAGEID IS NOT NULL AND B.PACKAGEID IS NOT NULL) THEN A.PACKAGEID END AS PACKAGEID,
CASE WHEN A.CUSTOMEROTP = B.CUSTOMEROTP THEN NULL
     WHEN A.CUSTOMEROTP IS NULL THEN NULL
     WHEN (B.CUSTOMEROTP IS NULL AND A.CUSTOMEROTP IS NOT NULL) OR (A.CUSTOMEROTP IS NOT NULL AND B.CUSTOMEROTP IS NOT NULL) THEN A.CUSTOMEROTP END AS CUSTOMEROTP,
CASE WHEN A.CLIENTOTP = B.CLIENTOTP THEN NULL
     WHEN A.CLIENTOTP IS NULL THEN NULL
     WHEN (B.CLIENTOTP IS NULL AND A.CLIENTOTP IS NOT NULL) OR (A.CLIENTOTP IS NOT NULL AND B.CLIENTOTP IS NOT NULL) THEN A.CLIENTOTP END AS CLIENTOTP
FROM
NEEDTOSYNCREQUESTS A
INNER JOIN
LASTSYNCEDREQUEST B
ON A.ID = B.ID;
另一答案

您可以尝试基于案例的查询,如下面的See live demo

select
    id      = N.id,
    Loadid  = case 
                when ISNULL(N.Loadid,'')=ISNULL(L.Loadid,'') 
                then NULL
                else N.LoadId
              end,
    Shipmentid=case 
                when ISNULL(N.Shipmentid,'')=ISNULL(L.Shipmentid,'') 
                then NULL
                else N.Shipmentid
              end,
    orderid=case 
                when ISNULL(N.orderid,'')=ISNULL(L.orderid,'') 
                then NULL
                else N.orderid
              end,
    packageid=case 
                when ISNULL(N.packageid,'')=ISNULL(L.packageid,'') 
                then NULL
                else N.packageid
              end,
    customerOTP=case 
                when ISNULL(N.customerOTP,'')=ISNULL(L.customerOTP,'') 
                then NULL
                else N.customerOTP
              end,
    clientOTP=case 
                when ISNULL(N.clientOTP,'')=ISNULL(L.clientOTP,'') 
                then NULL
                else N.clientOTP
              end
from
NEEDTOSYNCREQUESTS N LEFT JOIN
LASTSYNCEDREQUEST L ON
N.id=L.id
另一答案

试试这个:

SELECT n.ID, n.LoadId, n.ShipmentId,
  n.OrderId, NULL PackageId, n.CustomerOTP,
  n.ClientOTP
FROM NEEDTOSYNCREQUESTS AS n
INNER JOIN LASTSYNCEDREQUEST AS l ON n.ID = l.ID AND n.LoadId = l.LoadId
WHERE n.CustomerOTP <> l.CustomerOTP AND
      n.ClientOTP   <> l.ClientOTP
  AND n.ShipmentId IS NOT NULL
  AND l.ShipmentId IS NULL
  AND l.OrderId IS NOT NULL
  AND l.ShipmentId IS NULL;

SQL Fiddle Demo

| ID | LoadId | ShipmentId | OrderId | PackageId | CustomerOTP | ClientOTP |
|----|--------|------------|---------|-----------|-------------|-----------|
|  1 |     L1 |        123 |  (null) |    (null) |       99999 |     88888 |

请注意,我不明白为什么PackageId应为null,因为根据您的标准,它不应该。无论如何,我选择它作为一个固定的NULL值,这样无论实际值是多少,你总会得到一个NULL值。

另一答案

在创建数据提取或集成时,我经常需要解决这种情况。

所以我的答案将接近于此:

如果要为某些列自定义它,可以使用MERGE函数并添加一些开关案例

MERGE LASTSYNCEDREQUEST TGT
USING (
 SELECT 
  ID,
  LoadId,
  ShipmentId,
  OrderId,
  PackageId,
  CustomerOTP,
  ClientOTP

FROM NEEDTOSYNCREQUESTS
) AS SRC
ON (
        SRC.ID = TGT.ID)

WHEN MATCHED
THEN
    UPDATE
    SET     
     TGT.ID = SRC.ID
    ,TGT.LoadID = NULL
    ,TGT.ShipmentID = SRC.ShipmentID
    ,TGT.OrderID = NULL
    ,TGT.PackageID = NULL
    ,TGT.CustomerOTP = SRC.CustomerOTP
    ,TGT.ClientOTP = SRC.ClientOTP


WHEN NOT MATCHED
THEN
    INSERT (

        ID,
        LoadId,
        ShipmentId,
        OrderId,
        PackageId,
        CustomerOTP,
        ClientOTP

        )
    VALUES (
         SRC.ID,
         NULL,
         SRC.ShipmentId,
         NULL,
         NULL,
         SRC.CustomerOTP,
         SRC.ClientOTP

        );

SELECT * FROM LASTSYNCEDREQUEST

你可以试试我上面写的代码。

以上是关于从两个表中选择不匹配的列值的主要内容,如果未能解决你的问题,请参考以下文章

根据 SQL Server 中表中的列值从两个表中获取一个新表:

Laravel - 从数据透视表中获取额外的列值

如何覆盖 bigquery 现有表中的列值

如何连接两个表并选择不匹配的列

用另一个表中的列值替换列的空值

oracle sql查询以获取没有空格的列值