【问题标题】:How to remove null values in lat long in sql如何在sql中删除lat long中的空值
【发布时间】:2021-02-25 17:31:40
【问题描述】:

我正在使用下面的查询,它给了我一个错误。我得到的错误在最底部。该错误是由我的一些事务中的 lat 和 long 具有空值引起的。我已将代码放入其中以删除 3 个表中每个表中的 lat 和 long 中的所有 null。

我该怎么做才能使查询正常工作。查询工作正常并输出大约 100 行,直到遇到第一个空值然后抛出错误。

SELECT DISTINCT
    a.region,
    c.Market_zone,
    c.delivery_center_zone,
    a.period,
    a.E3Location_num,
    a.dad_name,
    a.dad_latitude, 
    a.dad_longitude,
    c.lat,
    c.long,
    z.latitude,
    z.longitude,
    a.event_date,
    a.units,
    a.driver_num,
    d.driver_name,
    a.delivery_reason,
    b.description,
    c.wsensor,
    a.autowillstatus,
    a.delivery_exception,
    a.phone_order,
    a.cancel,
    c.lob,
    a.zone,
    a.keyindex,
    f.exception_reasons,
    ACOS(COS(RADIANS(90-a.dad_latitude)) *COS(RADIANS(90-c.lat)) +SIN(RADIANS(90-a.dad_latitude)) *SIN(RADIANS(90-c.lat)) *COS(RADIANS(a.dad_longitude-c.long))) *6371 as kms_from_tank,
    CASE 
        WHEN ACOS(COS(RADIANS(90-a.dad_latitude)) *COS(RADIANS(90-c.lat)) +SIN(RADIANS(90-a.dad_latitude)) *SIN(RADIANS(90-c.lat)) *COS(RADIANS(a.dad_longitude-c.long))) *6371 > 5 then 'N'
        ELSE 'Y'
    END as Cancelled_on_Tanksite,
    ACOS(COS(RADIANS(90-a.dad_latitude)) *COS(RADIANS(90-z.latitude)) +SIN(RADIANS(90-a.dad_latitude)) *SIN(RADIANS(90-z.latitude)) *COS(RADIANS(a.dad_longitude-z.longitude))) *6371 as kms_from_yard,
    CASE 
        WHEN ACOS(COS(RADIANS(90-a.dad_latitude)) *COS(RADIANS(90-z.latitude)) +SIN(RADIANS(90-a.dad_latitude)) *SIN(RADIANS(90-z.latitude)) *COS(RADIANS(a.dad_longitude-z.longitude))) *6371 > 5 then 'N'
        ELSE 'Y'
    END as Cancelled_at_Yard,
    a.E3Location_num + '-' + CAST(a.event_date AS varchar (50)) AS unique_id,
    a.size,
    CASE 
        WHEN a.size = '2222' THEN 'MMT'
        WHEN a.size = '22222' THEN 'MMT'
        WHEN a.size = '0' THEN 'Cyl'
        ELSE 'BULK'
    END AS Department 
FROM
    e3.dbo.E3table_1 (nolock)a
LEFT JOIN
    (SELECT * FROM openquery(suppro_supw, 'SELECT reason_id, description
                                           FROM DELIVERY_REASON
                                           AT isolation 0')) b ON a.delivery_reason = b.reason_id
LEFT JOIN
    (SELECT * FROM [SPPWEBPDNJ04].[Delivery_Customer_Master].[dbo].[Del_Customer_Master] 
     WHERE lat IS NOT NULL AND long IS NOT NULL) c ON c.Location = a.E3Location_num 
LEFT JOIN
    (SELECT * FROM openquery(suppro_supw, 'SELECT driver_id, driver_name
                                           FROM DRIVER_HEADER 
                                           AT isolation 0')) d ON d.driver_id = a.driver_num
LEFT JOIN
    (SELECT * FROM openquery(SUPPRO_SUPW, 'SELECT
cc.full_account
,ee.tank_num 
,aa.name
,ee.driver_num
,aa.delivery_hold
,aa.department_code
,dd.size
,bb.exception_reasons
,dd.delivery_type
,ee.event_date

FROM
ACCOUNTS aa,
DELIVERY_EXCEPTION bb,
FULL_ACCOUNT cc,
TRANS_DELIVERY dd,
TRANS_MAIN ee

WHERE
aa.account_num = bb.account_num
AND aa.account_num = cc.account_num
AND aa.account_num = dd.account_num
AND aa.account_num = ee.account_num
AND bb.account_num = cc.account_num
AND bb.account_num = dd.account_num
AND bb.trx_unique_key = dd.trx_unique_key
AND bb.trx_unique_key = ee.trx_unique_key
AND cc.account_num = dd.account_num
AND ee.event_date > "2020-01-01" 
and bb.exception_reasons like ''%SECOND%'' 

AT ISOLATION 0'))f
on rtrim(f.full_account)+'-'+cast(f.tank_num as varchar (3)) = a.E3Location_num
and f.event_date = a.event_date

left join
(Select * FROM e3.dbo.ADDs_Delivery_centers_info (nolock) where latitude is not null and longitude is not null) z
on z.Delivery_center_num = a.cost_center

where 
a.driver_num > 0
and truck_num > 0 
and a.units >= 0
and a.event_date > '2019-01-01'
and a.Posting_code in (1,2,10,99)
and a.region in ('AB1','BC1','PR1')
and a.dad_latitude is not null 
and a.dad_longitude is not null 

我收到一个错误:

消息 3623,第 16 级,状态 1,第 1 行
发生域错误

【问题讨论】:

  • 此错误表明您正在使用的一个或多个数学函数的参数错误,例如 LOG(-1) 或 SQRT(-1),在数学上没有意义,SQL 返回错误信息
  • 我假设您使用的是 sql server 2005 ,因为错误消息文本在 2005 年之后的下一个 sql server 版本中有所更改
  • 是,使用 sql server 2005

标签: sql sql-server sql-server-2005


【解决方案1】:

当 JOIN 语句未能在表的右侧找到匹配项时,LEFT JOIN 允许通过空值。

例如,当你

left join
(Select * FROM e3.dbo.ADDs_Delivery_centers_info (nolock) 
where latitude is not null and longitude is not null) z 
  on z.Delivery_center_num = a.cost_center

当没有匹配的z.Delivery_center_num 时,您将拥有null z.latitude。与其他表相同。

要么 INNER JOIN 这些表每次都保证值,要么处理每个数学运算中的空可能性。

编辑:

在查看了 BOL 之后(因为我的三角函数很糟糕),它看起来好像是 ACOS will throw that exact error if the value is outside the range of -1 to 1。我们需要在 ACOS 语句中进行错误处理,但是在您的查询中看起来很可怕,因此我建议您创建一个 UDF 来为您干净地处理它。

例如,

-- Test: 
-- if this statement generates an error, replace the NULL in the function 
-- with 1. I don't have an old enough server to confirm whether it could handle NULL. 
select ACOS(null) 
go


create function myACOS (@inp float)
returns float 
as begin 
declare @ret float 
    
    select @ret = 
        acos(   /* check whether our input exceeds the boundaries of ACOS; if it does, replace it with something harmless */
                case when @inp < -1 or @inp > 1 then null 
                else @inp end)
    
return @ret
end

然后,您更新您的 SELECT 语句以在任何地方使用此函数而不是内置 ACOS,因此它会在幕后处理您的错误:

SELECT 
   dbo.myACOS(COS(blah blah blah...)) *6371 as kms_from_tank

【讨论】:

  • 谢谢,我将所有联接更改为内部联接,但问题仍然存在,抱歉,您能否举个例子说明如何“在每个数学运算中处理空可能性。”,您的意思是在每个括号中Acos(cos(Radians..) 我应该处理 null 值?如果你能以某种方式给我一个如何编写它的例子会有所帮助?
  • 我在线查看了这些书籍(从技术上讲,you 在发布之前也应该检查一下),看起来 ACOS 是您查询中唯一可以提供的功能那个错误。我更新了我的答案以反映如何干净地处理它。但是,将来处理空值实际上是 ISNULL(myCol, 1) 或您希望替换值的任何值。所以,COS(RADIANS(90-ISNULL(a.dad_latitude, 0))) 是处理 NULL 值的方法,如果这些是给你错误的原因。 (他们不是。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
相关资源
最近更新 更多