简体   繁体   中英

pervasive query with group by issue

I am trying to run this query on pervasive database

select cust_no,cust_name,sum(bvtotal) as Amount
from sales_history_header  
where cust_no is not null and number is not null and bvtotal > 1000 and in_date < 20140101
group by cust_no,cust_name
order by sum(bvtotal) desc;

How do I exclude those group results which had in_date > 20140101 in there sub results ?

This query I have is also fetching those results which had in_date > 20140101

Am I doing something wrong ?

The sample output I am getting is in this format

cust_no     cust_name      amount
A             a1            500
B             b1            500
C             c1            1000

I want to exclude this record with cust_no 'A' because it had transaction with in_date in 20140202

consider in my raw data I have records like

cust_no     cust_name      amount    in_date
A             a1            100      20130203
A             a1            400      20130101
A             a1            1000     20140503

You need to exclude all records based on a set of ids. Typically, you do this with a subquery:

SELECT cust_no,
    cust_name,
    sum(bvtotal) AS Amount
FROM sales_history_header
WHERE cust_no IS NOT NULL
    AND number IS NOT NULL
    AND bvtotal > 1000
    AND cust_no NOT IN (
        SELECT cust_no 
        FROM sales_history_header 
        WHERE in_date >= 20140101 
            AND cust_no IS NOT NULL
    )
GROUP BY cust_no,
    cust_name
ORDER BY sum(bvtotal) DESC;

The AND cust_no IS NOT NULL portion of the subquery is to avoid problems with NOT IN and NULL values. You may have better performance if you rewrite this as a NOT EXISTS correlated subquery, but in my experience MySQL is pretty bad at those.

Another alternative is the more explicit self-anti-join approach (LEFT JOIN and filter where right table is null) but that is kind of... sketchy feeling?... because you appear to allow cust_no to be NULL and because it's a query that's aggregating so it feels like you have to worry about multiplying rows:

SELECT s1.cust_no,
    s1.cust_name,
    sum(s1.bvtotal) AS Amount
FROM sales_history_header s1
LEFT JOIN (
        SELECT cust_no
        FROM sales_history_header
        WHERE cust_no IS NOT NULL
            AND number IS NOT NULL
            AND bvtotal > 1000
            AND in_date >= 20140101) s2
    ON  s2.cust_no = s1.cust_no
WHERE s1.cust_no IS NOT NULL
    AND s1.number IS NOT NULL
    AND s1.bvtotal > 1000
    AND s2.cust_no IS NULL
GROUP BY cust_no,
    cust_name
ORDER BY sum(bvtotal) DESC;

The LEFT JOIN combined with WHERE [...] s2.cust_no IS NULL is the part that eliminates the records you don't want.

I think you need to specify you date constant as a date unless you really want to be dealing with integers.

select cust_no,cust_name,sum(bvtotal) as Amount
from sales_history_header  
where cust_no is not null and number is not null and bvtotal > 1000 and in_date < '2014-01-01'
group by cust_no,cust_name
order by sum(bvtotal) desc;

I don't understand what exactly you need,

But it seems that you mixed types INT and DATE.

So if your in_date field has type DATE

select 
  cust_no,
  cust_name,
  sum(bvtotal) as Amount
from sales_history_header  
where cust_no is not null 
  and number is not null 
  and bvtotal > 1000 
  and in_date < DATE('2014-01-01')
group by cust_no,cust_name
order by sum(bvtotal) desc;

If your in_date field has type TIMESTAMP

select 
  cust_no,
  cust_name,
  sum(bvtotal) as Amount
from sales_history_header  
where cust_no is not null 
  and number is not null 
  and bvtotal > 1000 
  and in_date < TIMESTAMP('2014-01-01 00:00:00')
group by cust_no,cust_name
order by sum(bvtotal) desc;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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