简体   繁体   English

SQL UNION无法使用2个HAVING子句

[英]SQL UNION not working with 2 HAVING clauses

I want to use UNION to join two SQL SELECT queries. 我想使用UNION联接两个SQL SELECT查询。 I need the final data to use the HAVING clause to filter the entire query. 我需要最终数据以使用HAVING子句来过滤整个查询。 Here is my statement: 这是我的声明:

SELECT CLIENT, 
       BIZNAME, 
       BIZSTREET, 
       BIZCITY, 
       BIZSTATE, 
       BIZZIP, 
       BIZPHONE, 
       URL, 
       LAT, 
       LNG, 
       CONSOLIDATED, 
       ( 3959 * ACOS(COS(RADIANS('%s')) * COS(RADIANS(LAT)) * COS( 
                     RADIANS(LNG) - RADIANS('%s')) 
                              + SIN 
                              (RADIANS('%s')) * SIN(RADIANS(LAT))) ) AS distance 
FROM   BizInfo 
       INNER JOIN WebSites 
               ON WebSites.CUSTOMER = BizInfo.CUSTOMER 
WHERE  BizInfo.CLIENT = 'GCB' 
       AND WebSites.STATUS <> 'Cancel' 
       AND WebSites.STATUS <> 'In Progress' 
       AND WebSites.STATUS <> 'Review' 
       AND WebSites.STATUS <> 'Testing' 
UNION 
SELECT CLIENT, 
       BIZNAME, 
       BIZSTREET, 
       BIZCITY, 
       BIZSTATE, 
       BIZZIP, 
       BIZPHONE, 
       'http://www.abc-site.com', 
       LAT, 
       LNG, 
       '0', 
       ( 3959 * ACOS(COS(RADIANS('%s')) * COS(RADIANS(LAT)) * COS( 
                     RADIANS(LNG) - RADIANS('%s')) 
                              + SIN 
                              (RADIANS('%s')) * SIN(RADIANS(LAT))) ) AS distance 
FROM   BizInfo 
WHERE  CLIENT = 'GCB' 
       AND BIZNAME = 'Acme' 
HAVING DISTANCE < '%s' 
ORDER  BY DISTANCE 
LIMIT 0, 200 

I read on this site http://www.really-fine.com/SQL_union.html (GROUP BY and HAVING clauses can be used only within individual queries and cannot be used to affect the final results set. ), but I don't understand how to implement this or if it is correct. 我在此网站上阅读了http://www.really-fine.com/SQL_union.html(GROUP BY和HAVING子句只能在单个查询中使用,而不能用于影响最终结果集。),但是我不会不了解如何实施此方法或该方法是否正确。

How do I properly write this SQL query? 如何正确编写此SQL查询?

HAVING can only be used in an aggregate query with a GROUP BY clause. HAVING只能在带有GROUP BY子句的聚合查询中使用。 Your queries do not. 您的查询没有。 Use WHERE instead. 请改用WHERE。

  1. Those are scalar functions, not aggregate functions. 这些是标量函数,而不是聚合函数。 So to filter on the result, use the WHERE clause, not the HAVING clause. 因此,要过滤结果,请使用WHERE子句,而不要使用HAVING子句。 You are filtering horizontally, not vertically. 您正在水平过滤,而不是垂直过滤。

  2. You cannot use a column alias in the WHERE clause, so you have to restate the functions used in the SELECT list (I've done that in the query below). 您不能在WHERE子句中使用列别名,因此必须重新声明SELECT列表中使用的函数(我在下面的查询中已完成此操作)。

Try the following. 尝试以下方法。 There are 2 issues at play. 有2个问题在起作用。

SELECT Client,
       BizName,
       BizStreet,
       BizCity,
       BizState,
       BizZip,
       BizPhone,
       url,
       lat,
       lng,
       Consolidated,
       (3959 * acos(cos(radians('%s')) * cos(radians(lat)) *
                    cos(radians(lng) - radians('%s')) +
                    sin(radians('%s')) * sin(radians(lat)))) AS distance
  FROM BizInfo
 INNER JOIN WebSites
    ON WebSites.Customer = BizInfo.Customer
 WHERE BizInfo.Client = 'GCB'
   AND WebSites.Status <> 'Cancel'
   AND WebSites.Status <> 'In Progress'
   AND WebSites.Status <> 'Review'
   AND WebSites.Status <> 'Testing'
UNION
SELECT Client,
       BizName,
       BizStreet,
       BizCity,
       BizState,
       BizZip,
       BizPhone,
       'http://www.abc-site.com',
       lat,
       lng,
       '0',
       (3959 * acos(cos(radians('%s')) * cos(radians(lat)) *
                    cos(radians(lng) - radians('%s')) +
                    sin(radians('%s')) * sin(radians(lat)))) AS distance
  FROM BizInfo
 WHERE Client = 'GCB'
   AND BizName = 'Acme'
   and (3959 * acos(cos(radians('%s')) * cos(radians(lat)) *
                    cos(radians(lng) - radians('%s')) +
                    sin(radians('%s')) * sin(radians(lat)))) < '%s'
 ORDER BY distance LIMIT 0, 200

You can probably solve that very easily by wrapping everything into a subquery. 您可以通过将所有内容包装到子查询中来轻松解决该问题。 Something like : 就像是 :

SELECT
  *
FROM
  (
      SELECT Client, BizName, BizStreet, BizCity, BizState, BizZip, BizPhone, url, lat, lng, Consolidated,
      ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) )
      AS distance FROM BizInfo
      INNER JOIN WebSites ON WebSites.Customer = BizInfo.Customer
      WHERE BizInfo.Client = 'GCB'
      AND WebSites.Status <> 'Cancel' AND WebSites.Status <> 'In Progress' AND WebSites.Status <> 'Review' AND WebSites.Status <> 'Testing' 
      UNION SELECT Client, BizName, BizStreet, BizCity, BizState, BizZip, BizPhone, 'http://www.abc-site.com', lat, lng, '0', 
      ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) )
      AS distance FROM BizInfo WHERE Client = 'GCB' AND BizName = 'Acme'
  ) AS ClientInfo
WHERE 
  distance < '%s' 
ORDER BY 
  distance 
LIMIT 0 , 200

This is the fastest path to what you want but it is not very clean. 这是您想要的最快途径,但不是很干净。

Also please tell me that all those parameters are not vulnerable to SQL injection ...? 还请告诉我,所有这些参数都不易受到SQL注入的影响 ...?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM