如何区分来自非匹配记录的null和来自左连接中的非现有记录的null?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何区分来自非匹配记录的null和来自左连接中的非现有记录的null?相关的知识,希望对你有一定的参考价值。

下面的语句创建表,数据和有问题的选择。

目标是当没有custid 1的订单时,我想显示“没有找到任何订单”,如果有custid 1的订单记录而不是电视的订单记录,我想显示'找到订单但不是电视订单' 。在这两种情况下,t.description都将为NULL,但我需要区分两种NULL情况。如何区分它们,以便前两个WHEN语句可以相应地处理每个语句?

CREATE TABLE [dbo].[Customer](
    [CustId] [int] NOT NULL,
    [CustomerName] [varchar](50) NOT NULL
)

CREATE TABLE [dbo].[Order](
    [OrderId] [int] NOT NULL,
    [CustId] [int] NOT NULL,
    [Description] [varchar](50) NOT NULL
)



INSERT INTO customer (CustId, CustomerName) VALUES
(1, 'John'),
(2, 'Tom')
GO

INSERT INTO [order] (OrderId, CustId, Description) VALUES
(1, 2, 'TV')
go

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
    DROP TABLE #temp;

SELECT

    'TV' Description INTO #temp

SELECT c.CustId
    ,t.Description
   ,o.Description
   ,CASE
        WHEN t.Description IS NULL THEN 'Did not find any orders'
        WHEN t.Description IS NULL THEN 'Found order but not TV order'
        ELSE 'Found TV Order' 
    END Status

FROM Customer c
LEFT JOIN [Order] o
    ON o.CustId = c.CustId
LEFT JOIN #temp t
    ON t.Description = o.Description
WHERE c.CustId = 1

更新:

#temp表具有要搜索的条件。在这种情况下'电视'。

答案

如果您只想显示有关客户的信息,请使用聚合:

SELECT c.CustId,
       (CASE WHEN COUNT(o.CustId) = 0
             THEN 'Did not find any orders'
             WHEN SUM(CASE WHEN o.Description = 'TV' THEN 1 ELSE 0 END) = 0
            THEN 'Found order but not TV order'
            ELSE 'Found TV Order' 
       END) as Status
FROM Customer c LEFT JOIN 
     [Order] o
     ON o.CustId = c.CustId
WHERE c.CustId = 1
GROUP BY c.CustId;

请注意,我不知道#temp用于什么。

此外,如果您希望在客户级别获取信息,则不应在SELECT中包含订单级信息。

另一答案

///你可以试试这个。

 select a.custid,a.CustomerName,orderid=isnull(b.orderId,0),
     description=iif(b.description is null,'Did not Find Any Order',b.description) 
     from Customer a left join [Order] b on a.custid=b.Custid
另一答案

这个问题并不完全清楚,但我认为临时表#temp是您想要查看的描述列表。

所以我可以想到几种不同的方法,例如你可以使用OUTER APPLY

select
    c.CustId,
    t.Description,
    case
        when o.Description is null then
            'Did not find any orders'
        when o.Description <> t.Description then
            concat('Found order but not ',t.Description,' order')
        else
            concat('Found ',t.Description,' order')
    end as status
from dbo.Customer as c
    cross join (
        select 'TV' as Description
    ) as t
    outer apply (
        select top 1 tt.Description
        from dbo.[Order] as tt
        where
            tt.CustId = c.CustId
        order by
            case when tt.Description = t.Description then 0 else 1 end
    ) as o

sql fiddle demo

或者您可以使用左连接和外部应用:

select
    c.CustId,
    t.Description,
    case
        when o1.Description is not null then
            concat('Found ',t.Description,' order')
        when o2.OrderId is not null then
            concat('Found order but not ',t.Description,' order')
        else
            'Did not find any orders'
    end as status
from dbo.Customer as c
    cross join (
        select 'TV' as Description
    ) as t
    left join dbo.[Order] as o1 on
        o1.CustId = c.CustId and
        o1.Description = t.Description
    outer apply (
        select top 1 tt.OrderId
        from dbo.[Order] as tt
        where
            tt.CustId = c.CustId and
            tt.Description <> t.Description
    ) as o2

sql fiddle demo

另一答案

这可能对你有帮助,不确定。

案例陈述:

,case when  t.Description = o.Description  then 'Found TV Order'
         when  isnull(t.Description,'No') = isnull(o.Description,'No') then 'Did not find any orders'
         when  isnull(t.Description,'No') <> isnull(o.Description,'No') then 'Found order but not TV order'
   end Status

修改查询:

SELECT c.CustId
    ,t.Description tdesc
   ,o.Description odesc

   ,case when  t.Description = o.Description  then 'Found TV Order'
         when  isnull(t.Description,'No') = isnull(o.Description,'No') then 'Did not find any orders'
         when  isnull(t.Description,'No') <> isnull(o.Description,'No') then 'Found order but not TV order'
   end Status
  /*  ,CASE
        WHEN t.Description IS NULL THEN 'Did not find any orders'
        WHEN t.Description IS NULL THEN 'Found order but not TV order'
        ELSE 'Found TV Order' 
    END Status  */

FROM Customer c
LEFT JOIN [Order] o ON o.CustId = c.CustId
LEFT JOIN #temp t   ON t.Description = o.Description

enter image description here

--------------------------- **旧代码低于** --------------- ------------------------------

 select CustId,descpt 
    from 
    (
    SELECT c.CustId
        , case when o.Description is null then 'Did not find any orders' end   descpt 
    FROM Customer c
    LEFT JOIN [Order] o ON o.CustId = c.CustId  ) no_orders
    where no_orders.descpt is not null

    union 
    select CustId,descpt 
    from 
    (
    SELECT c.CustId
        , case when o.Description ='TV' then 'Found order for TV ' end   descpt 
    FROM Customer c
    LEFT JOIN [Order] o ON o.CustId = c.CustId  ) no_orders
    where no_orders.descpt is not null

    union
    select CustId,descpt 
    from 
    (
    SELECT c.CustId
        , case when o.Description <> 'TV' then 'Found order but not TV order' end   descpt 
    FROM Customer c
    LEFT JOIN [Order] o ON o.CustId = c.CustId  ) no_orders
    where no_orders.descpt is not null

enter image description here

另一答案

首先,我假设订单表中的每个客户都可以存在多条记录。由于您需要知道是否有任何订单,但显然需要结果集,您无法根据所需的描述进行过滤...但如果您按客户(和描述)进行分组并使用计数,则可以函数,这也允许您在Order表中可能有许多记录时返回单个记录。

此外,由于您最终尝试根据两个结果集(电视订单和任何订单)回答两个问题,那么您将需要一些版本的两个查询。有几个选项,但子查询是最简单的。

这是SQL(我为此创建了临时表,并添加了更多记录):

CREATE TABLE [dbo].[Customer](
    [CustId] [int] NOT NULL,
    [CustomerName] [varchar](50) NOT NULL
)
CREATE TABLE [dbo].[Order](
    [OrderId] [int] NOT NULL,
    [CustId] [int] NOT NULL,
    [Description] [varchar](50) NOT NULL
)
CREATE TABLE [dbo].[FakeTemp](
    [Description] [varchar](50) NOT NULL
)
INSERT INTO FakeTemp (Description) VALUES
('TV')
GO
INSERT INTO customer (CustId, CustomerName) VALUES
(1, 'John'),
(2, 'Tom'),
(3, 'Steve')
GO
INSERT INTO [order] (OrderId, CustId, Description) VALUES
(1, 1, 'TV')
go
INSERT INTO [order] (OrderId, CustId, Description) VALUES
(2, 2, 'VCR')
go
INSERT INTO [order] (OrderId, CustId, Description) VALUES
(3, 1, 'VCR')
go


select c.CustomerName, count(OrderId) as TV_Orders
, (select count(OrderID) from [order] where CustId = 1) as All_Orders
from customer c
left outer join [order] o on c.CustId = o.CustId
inner join FakeTemp t on o.Description = t.Description
where c.CustID = 1
group by c.CustomerName, t.Description

这里是小提琴的链接(感谢Roman Pekar让我开始):http://sqlfiddle.com/#!18/eadc3/16/0

我没有做case语句,因为我认为你可以很容易地把它变成输出文本所需的case语句,这显示了更好的结果。

对于那些无法完成案例陈述的人,这里完整的完成了作业问题:

select
  CASE
      WHEN (select count(OrderID) from orders where CustId = 1) = 0 THEN 'Did not find any orders'
      WHEN count(OrderID) = 0 THEN 'Found order but not TV order'
      ELSE 'Found TV Order'
  End as Status

from customer c
left outer join [orders] o on c.CustId = o.CustId
inner join FakeTemp t on o.Description = t.Description
where c.CustID = 1
group by c.CustomerName, t.Description

以上是关于如何区分来自非匹配记录的null和来自左连接中的非现有记录的null?的主要内容,如果未能解决你的问题,请参考以下文章

《数据结构》遍历二叉树的非递归算法的疑问。

sed中的非贪婪(不情愿)正则表达式匹配?

如何使用 CoreML 处理来自相机的非方形帧?

字符串列表上的 BigQuery 左连接返回 null

来自倾斜容器的非倾斜背景图像[重复]

数据库力扣题组合两个表