合并2个案例查询并返回1或0

时间:2014-08-10 11:48:56

标签: sql sql-server case

我在vb.net中的2个单独函数中使用了2个验证查询。为通过我的应用程序处理的每个order_num调用这两个函数。我想将两个案例查询合并为一个,其中一个结果值为1或0.先谢谢。

第一次查询:

select case when EXISTS (
select 1
    from [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
    where segment IN ('PID','ZPI', 'ZRQ', 'ZSI') AND order_num = '780630021555'
) then 1 else 0 end as [SegmentsExist]

第二次查询:

SELECT CASE
WHEN
(SELECT COUNT(*) As result_count FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] 
with (nolock) WHERE segment = 'OBR' AND order_num = '780630021555') 
= 
(SELECT COUNT(*) As result_count FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] 
with (nolock)   WHERE segment = 'OBX' AND order_num = '780630021555')
THEN 1
ELSE 0
End AS returnValue

3 个答案:

答案 0 :(得分:1)

你可能遇到的更大问题是你的程序结构。您提到这些查询(或1个查询)将针对30k-40k订单运行。运行单个查询是一个荒谬的次数,特别是当您可以以基于集合的方式运行时。

我建议重构您的查询以运行整个数据集,将结果存储为VB中的数据集,然后从那里做您想做的事情。如果您为数据库中的每一行运行基于搜索/扫描的操作而不是返回数据集,那么您将无法获得良好的性能。

编辑:关于数据集的更多信息。

当您对单个结果(WHERE order_num = '780630021555')运行查询时,数据库必须查看表中的每一行,以确保它找到order_num ='780630021555'的所有记录。现在,你说有40k记录..这意味着对于这40,000次更新中的每一次,数据库必须查看表中的每一条记录。扫描40,000行表40,000次,最多可读取约16亿行。 SQL将尝试优化并可能少扫描表,但这基本上就是你正在做的事情。

执行此操作的理想方法是返回整个表的数据。写下您的查询以返回所有订单号的1或0,然后从那里进行处理。这样,表的40k行只读一次。像这样:

SELECT CASE
WHEN (segment IN ('PID','ZPI', 'ZRQ', 'ZSI') OR OBR_Count = OBX_Count) THEN 1 ELSE 0 END AS Valid_Record
FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] IOD with (nolock)
JOIN
(
    SELECT order_num, COUNT(segment) OBR_Count
    FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
    WHERE segment = 'OBR'
    GROUP BY order_num
) OBR
ON IOD.order_num = OBR.order_num
JOIN
(
    SELECT order_num, COUNT(segment) OBX_Count
    FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
    WHERE segment = 'OBX'
    GROUP BY order_num
) OBX
ON IOD.order_num = OBX.order_num

这应该为表格中的每个订单号返回一行。它将使用Valid_Record列返回它,指示您指定的条件是真(1)还是不是(0)。我没有运行此查询,但它看起来正确。运行需要一段时间,可能需要一分钟,但我可以保证您正在进行的操作单独选择每个结果需要花费很多倍。

我使用SQL Server中的几个表,每天有超过十亿行。在这些情况下,查询中的非常小的更改会使查询时间产生很大差异。在最大行数为40k的表中,您将通过重构查询来获得更多性能,从而为您提供数据集,而不是为您提供40k次单个结果。

答案 1 :(得分:0)

如果逻辑是“或”,你可以这样做:

select (case when EXISTS (select 1
                          from [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
                          where segment IN ('PID','ZPI', 'ZRQ', 'ZSI') AND
                                order_num = '780630021555'
                         )
             then 1
             when (SELECT COUNT(*) As result_count
                   FROM [Sonora].[dbo][tbl_Informatics_Orders_Data] with (nolock)
                   WHERE segment = 'OBR' AND order_num = '780630021555') =
                  (SELECT COUNT(*) As result_count
                   FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
                   WHERE segment = 'OBX' AND order_num = '780630021555'
                  )
             then 1
             else 0
        end) as [SegmentsExist];

如果逻辑是“和”:

select (case when EXISTS (select 1
                          from [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
                          where segment IN ('PID','ZPI', 'ZRQ', 'ZSI') AND
                                order_num = '780630021555'
                         ) and
                  (SELECT COUNT(*) As result_count
                   FROM [Sonora].[dbo][tbl_Informatics_Orders_Data] with (nolock)
                   WHERE segment = 'OBR' AND order_num = '780630021555') =
                  (SELECT COUNT(*) As result_count
                   FROM [Sonora].[dbo].[tbl_Informatics_Orders_Data] with (nolock)
                   WHERE segment = 'OBX' AND order_num = '780630021555'
                  )
             then 1
             else 0
        end) as [SegmentsExist];

编辑:

您可以简化第二个条件,直接返回10

                  (SELECT (case when sum(case when segment = 'OBR' then 1 else 0 end) =
                                     sum(case when segment = 'OBX' then 1 else 0 end)
                                then 1 else 0
                           end)
                   FROM [Sonora].[dbo][tbl_Informatics_Orders_Data] with (nolock)
                   WHERE segment IN ('OBR', 'OBX') AND order_num = '780630021555'
                  )

答案 2 :(得分:0)

你从哪里获得order_num?如果它是基于同一个查询的同一个数据库我宁愿采用完全不同的方法让SQL Server以基于集合的方式执行评估,而不是试图加速函数调用而仍然叫它几千次......