当前,我的查询选择了我的WHERE子句中指定的所有位置,并返回了所有包含提供邮政编码的位置的邮政编码。 我的目标是返回所有带有未提供送货地区的邮政编码的位置。数据库中有成千上万个邮政编码,所以不是NOT的选择,因为我需要将结果限制在这些邮政编码中。我觉得这很容易实现,但是解决方案使我逃脱了。
SELECT ORS.PostDate
,ORS.Name
,ORS.Address
,ORS.City
,ORS.State
,ORS.Zip
,ORS.DriverID
,W.FirstName
,W.LastName
,ORS.RouteID
FROM tblOrderRouteStops ORS WITH (NOLOCK)
INNER JOIN tblWorker W WITH (NOLOCK) ON W.WorkerID = ORS.DriverID
--Select all distinct zips from tblOrderRouteStops, then use where clause to filter them to specified locations.
FULL OUTER JOIN
(SELECT DISTINCT ORSS.Zip FROM
tblOrderRouteStops ORSS WITH (NOLOCK)) as B
ON B.Zip = ORS.Zip
WHERE ORS.PostDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND ORS.PostDate < dateadd(day,datediff(day,0,GETDATE()),0)
AND ORS.CustID = 104105
AND ORS.StopType = 1
AND (ORS.Zip = 16635
OR ORS.Zip = 25504
OR ORS.Zip = 28401
OR ORS.Zip = 28803
OR ORS.Zip = 30901
OR ORS.Zip = 31904
OR ORS.Zip = 35801
OR ORS.Zip = 37921
OR ORS.Zip = 38801
OR ORS.Zip = 39232
OR ORS.Zip = 46825
OR ORS.Zip = 49428
OR ORS.Zip = 50265
OR ORS.Zip = 54915
OR ORS.Zip = 67214
OR ORS.Zip = 72205
OR ORS.Zip = 72764
OR ORS.Zip = 72916
OR ORS.Zip = 79605)
答案 0 :(得分:1)
使用NOT IN
运算符,如
AND ORS.Zip NOT IN (16635,25504,....)
答案 1 :(得分:0)
这是一个快速的过程。我接受了原始查询并对其进行了修改,并使用“ before and after”变体,该变体基于最后使用AND
子句的情况。
首先,设置一个包含“目标”邮政编码的临时表。使用起来会更容易,SQL会产生更好的执行计划。
DECLARE @TargetZips table
(
Zip char(5) not null -- Replace with the datatype you are using
)
INSERT @TargetZips values
(16635)
,(25504)
,(28401)
,(28803)
,(30901)
,(31904)
,(35801)
,(37921)
,(38801)
,(39232)
,(46825)
,(49428)
,(50265)
,(54915)
,(67214)
,(72205)
,(72764)
,(72916)
,(79605)
然后查询:
SELECT
ORS.PostDate
,ORS.Name
,ORS.Address
,ORS.City
,ORS.State
,ORS.Zip
,ORS.DriverID
,W.FirstName
,W.LastName
,ORS.RouteID
FROM tblOrderRouteStops ORS
INNER JOIN tblWorker W
ON W.WorkerID = ORS.DriverID
--Select all distinct zips from tblOrderRouteStops, then use where clause to filter them to specified locations.
FULL OUTER JOIN (-- Restrict this to the set of zip codes you are intersted in
SELECT DISTINCT ORSS.Zip
FROM tblOrderRouteStops ORSS
INNER JOIN @TargetZips tz
on tz.Zip = ORSS.zip
) as B
ON B.Zip = ORS.Zip
WHERE ORS.PostDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND ORS.PostDate < dateadd(day,datediff(day,0,GETDATE()),0)
AND ORS.CustID = 104105
AND ORS.StopType = 1
将其包含在原始查询中
AND B.Zip is not null
在修改后的查询中添加
AND B.Zip is null
理想情况下,您有两个单独的查询。这样,您就可以避免使用FULL OUTER JOIN
了-我建议这样做,它们总是会让我感到紧张。
-编辑------------------------
以下内容,恕我直言,虽然很笨拙,但可以避免使用INSERT:
WITH cteTargetZip
as (-- Build a table set based entirely on a values clause
select Zip
from (values (16635)
,(25504)
,(28401)
,(28803)
,(30901)
,(31904)
,(35801)
,(37921)
,(38801)
,(39232)
,(46825)
,(49428)
,(50265)
,(54915)
,(67214)
,(72205)
,(72764)
,(72916)
,(79605)
) as TargetZips (Zip)
)
SELECT...
,然后在主查询中将@TargetZips
替换为cteTargetZips
。
-第二次编辑----------------------------------------- >
好吧,这有望完成必要的工作...
-- Query will return all zip codes in the CTE expression that are not found
-- in your selected delivery locations. On large tables it will perform
-- poorly, unless there is an index on tblOrderRouteStops.Zip
WITH cteTargetZip
as (-- Build a table set based entirely on a values clause
select Zip
from (values (16635)
,(25504)
,(28401)
,(28803)
,(30901)
,(31904)
,(35801)
,(37921)
,(38801)
,(39232)
,(46825)
,(49428)
,(50265)
,(54915)
,(67214)
,(72205)
,(72764)
,(72916)
,(79605)
) as TargetZips (Zip)
)
SELECT cte.Zip
FROM cteTargetZip cte
WHERE not exists (-- The set of delivered-to locations you are interested in
-- If every tblOrderRouteStops always has at least one tblWorker,
-- you can drop the join.
SELECT 1
FROM tblOrderRouteStops ORS
INNER JOIN tblWorker W
ON W.WorkerID = ORS.DriverID
WHERE ORS.PostDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND ORS.PostDate < dateadd(day,datediff(day,0,GETDATE()),0)
AND ORS.CustID = 104105
AND ORS.StopType = 1
AND ORS.Zip = cte.Zip -- Technically, this line makes it a correlated subquery
)