简体   繁体   English

SQL:HAVING子句

[英]SQL: HAVING clause

See the following SQL statement: 请参阅以下SQL语句:

SELECT datediff("d", MAX(invoice.date), Now) As Date_Diff
      , MAX(invoice.date) AS max_invoice_date
      , customer.number AS customer_number
FROM invoice 
    INNER JOIN customer 
        ON invoice.customer_number = customer.number
GROUP BY customer.number 

If the the following was added: 如果添加以下内容:

HAVING datediff("d", MAX(invoice.date), Now) > 365

would this simply exclude rows with Date_Diff <= 365? 这会简单地排除Date_Diff <= 365的行吗?

What should be the effect of the HAVING clause here? 这里的HAVING条款会有什么影响?

EDIT: I am not experiencing what the answers here are saying. 编辑:我没有体验到这里的答案。 A copy of the mdb is at http://hotfile.com/dl/40641614/2353dfc/test.mdb.html (no macros or viruses). mdb的副本位于http://hotfile.com/dl/40641614/2353dfc/test.mdb.html (无宏或病毒)。 VISDATA.EXE is being used to execute the queries. VISDATA.EXE用于执行查询。

EDIT2: I think the problem might be VISDATA, because I am experiencing different results via DAO. EDIT2:我认为问题可能是VISDATA,因为我通过DAO遇到了不同的结果。

As already pointed out, yes, that is the effect. 正如已经指出的那样,是的,就是效果。 For completeness, 'HAVING' is like 'WHERE', but for the already aggregated (grouped) values (such as, MAX in this case, or SUM, or COUNT, or any of the other aggregate functions). 为了完整性,'HAVING'类似于'WHERE',但是对于已经聚合的(分组的)值(例如,在这种情况下为MAX,或SUM,或COUNT,或任何其他聚合函数)。

是的,它会排除那些行。

是的,这就是它会做的。

WHERE applies to all of the individual rows, so WHERE MAX(...) would match all rows. WHERE适用于所有单独的行,因此WHERE MAX(...)将匹配所有行。

HAVING is like WHERE, but within the current group. HAVING就像WHERE,但在当前组内。 That means you can do things like HAVING count(*) > 1, which will only show groups with more than one result. 这意味着您可以执行HAVING count(*)> 1之类的操作,这只会显示具有多个结果的组。

So to answer your question, it would only include rows where the record in the group that has the highest (MAX) date is greater than 365. In this case you are also selecting MAX(date), so yes, it excludes rows with date_diff <= 365. 所以要回答你的问题,它只会包含那些具有最高(MAX)日期的组中的记录大于365的行。在这种情况下,你也选择MAX(日期),所以是的,它排除了date_diff的行<= 365。

However, you could select MIN(date) and see the minimum date in all the groups that have a maximum date of greater than 365. In this case it would not exclude "rows" with date_diff <= 365, but rather groups with max(date_diff) <= 365. 但是,您可以选择MIN(日期)并查看最大日期大于365的所有组中的最小日期。在这种情况下,它不会排除date_diff <= 365的“行”,而是排除max的组( date_diff)<= 365。

Hopefully it's not too confusing... 希望它不会太混乱......

You may be trying the wrong thing with your MAX. 你的MAX可能会做错了。 By MAXing the invoice.date column you are effectively looking for the most recent invoice associated with the customer. 通过MAXing invoice.date列,您可以有效地查找与客户关联的最新发票。 So effectively the HAVING condition is selecting all those customers who have not had any invoices within the last 365 days. 因此,有效的HAVING条件是选择在过去365天内没有 任何发票的所有客户。

Is this what you are trying to do? 这是你想要做的吗? Or are you actually trying to get all customers who have at least one invoice from more than a year ago? 或者您是否真的试图让所有拥有一年多至少一张发票的客户? If that is the case, then you should put the MAX outside the datediff function. 如果是这种情况,那么你应该将MAX放在datediff函数之外。

That depends on whether you mean rows in the table or rows in the result. 这取决于您是表示表中的行还是结果中的行。 The having clause filters the result after grouping, so it would elliminate customers, not invoices. having子句在分组后过滤结果,因此它会消除客户,而不是发票。

If you want to filter out the new invoices rather than the customers with new invoices, you should use where instead so that you filter before grouping: 如果您要过滤掉新发票而不是新发票的客户,则应使用其他where以便在分组前进行过滤:

select
  datediff("d",
  max(invoice.date), Now) As Date_Diff,
  max(invoice.date) as max_invoice_date,
  customer.number
from
  invoice 
  inner join customer on invoice.customer_number = customer.number
where
  datediff("d", invoice.date, Now) > 365
group by
  customer.number

I wouldn't use a GROUP BY query at all. 我根本不会使用GROUP BY查询。 Using standard Jet SQL: 使用标准Jet SQL:

  SELECT Customer.Number
  FROM [SELECT DISTINCT Invoice.Customer_Number
     FROM Invoice
     WHERE (((Invoice.[Date])>Date()-365));]. AS Invoices 
  RIGHT JOIN Customer ON Invoices.Customer_Number = Customer.Number
  WHERE (((Invoices.Customer_Number) Is Null));

Using SQL92 compatibility mode: 使用SQL92兼容模式:

  SELECT Customer.Number
  FROM (SELECT DISTINCT Invoice.Customer_Number
     FROM Invoice
     WHERE (((Invoice.[Date])>Date()-365));) AS Invoices 
  RIGHT JOIN Customer ON Invoices.Customer_Number = Customer.Number
  WHERE (((Invoices.Customer_Number) Is Null));

The key here is to get a set of the customer numbers who've had an invoice in the last year, and then doing an OUTER JOIN on that result set to return only those not in the set of customers with invoices in the last year. 这里的关键是获取一组去年有发票的客户编号,然后对该结果集进行OUTER JOIN,以便仅返回去年没有发票的客户组中的那些客户编号。

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

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