按组SQL运行总计(Oracle)

时间:2014-03-03 19:21:21

标签: sql oracle running-total

我在Oracle数据库中有一个表,其中包含以下感兴趣的字段:位置,产品,日期,金额。我想编写一个查询,按位置,产品和日期获得总计金额。我在下面列出了我想要的结果示例表。

我可以获得一个总计,但是当我到达新的位置/产品时,我无法重置它。这是我到目前为止的代码,任何帮助都会非常感激,我觉得这是一个简单的修复。

select a.*, sum(Amount) over (order by Location, Product, Date) as Running_Amt
from Example_Table a

+----------+---------+-----------+------------+------------+
| Location | Product | Date      | Amount     |Running_Amt |
+----------+---------+-----------+------------+------------+
| A        | aa      | 1/1/2013  | 100        | 100        |
| A        | aa      | 1/5/2013  | -50        | 50         |
| A        | aa      | 5/1/2013  | 100        | 150        |
| A        | aa      | 8/1/2013  | 100        | 250        |
| A        | bb      | 1/1/2013  | 500        | 500        |
| A        | bb      | 1/5/2013  | -100       | 400        |
| A        | bb      | 5/1/2013  | -100       | 300        |
| A        | bb      | 8/1/2013  | 250        | 550        |
| C        | aa      | 3/1/2013  | 550        | 550        |
| C        | aa      | 5/5/2013  | -50        | 600        |
| C        | dd      | 10/3/2013 | 999        | 999        |
| C        | dd      | 12/2/2013 | 1          | 1000       |
+----------+---------+-----------+------------+------------+

3 个答案:

答案 0 :(得分:4)

啊,我想我已经明白了。

select a.*, sum(Amount) over (partition by Location, Product order by Date) as Running_Amt
from Example_Table a

答案 1 :(得分:2)

来自Oracle 10g中的高级SQL函数,它有这个例子。

import re, string, sys
import csv
import os 

class PictureString:

    REPEATS_RE = re.compile(r'(.)\((\d+)\)')
    #print REPEATS_RE
    FLOAT_RE = re.compile(r'S?[9Z]*[.V][9Z]+')
    INTEGER_RE = re.compile(r'S?[9Z]+')
    INTEGER_RE1 = re.compile(r'[9Z]+')
    COMP_TYPES = ['Integer', 'Float', 'Double', 'BCD']

    def expand_repeat_chars(self, pic_str):
        while True:
            match = self.REPEATS_RE.search(pic_str)
            #print match
            if not match:
                break
            expanded_str = match.group(1) * int(match.group(2))
            #print expanded_str
            #pic_str = self.REPEATS_RE.sub(expanded_str, pic_str, 1)
            pic_str=expanded_str
            print pic_str

        return pic_str

    def parse(self, pic_str, comp=0):
        pic_str = self.expand_repeat_chars(pic_str)
        if comp:
            data_type = self.COMP_TYPES[int(comp)]
        elif self.FLOAT_RE.match(pic_str):
            data_type = 'Float'
        elif self.INTEGER_RE.match(pic_str):
            data_type = 'Integer'
        elif self.INTEGER_RE1.match(pic_str):
            data_type = 'Integer'
        else:
            data_type = 'Char'
        decimal_pos = 0
        if 'V' in pic_str:
            decimal_pos = pic_str.index('V') + 1
            #print decimal_pos
            pic_str = pic_str.replace('V', '')
        result = (data_type, len(pic_str), decimal_pos)
        writer=csv.writer(csv_file)
        writer.writerow(result)
        #print result
        return result


class Field:

    FIELD_PTRN = r'^(?P<level>\d{2})\s+(?P<name>\S+)'
    PIC_PTRN = r'\s+PIC\s+(?P<pic>\S+)'
    DEPENDING_ON_PTRN = r'\s+OCCURS.*DEPENDING ON (?P<occurs>\S+)'
    OCCURS_PTRN = r'\s+OCCURS (?P<occurs>\d+) TIMES'
    COMP_PTRN = r'\s+COMP-(?P<comp>[1-3])'
    FIELD_RE = [ re.compile(i + '.') for i in [
        FIELD_PTRN + PIC_PTRN + COMP_PTRN,
        FIELD_PTRN + DEPENDING_ON_PTRN,
        FIELD_PTRN + OCCURS_PTRN + PIC_PTRN + COMP_PTRN,
        FIELD_PTRN + OCCURS_PTRN + PIC_PTRN,
        FIELD_PTRN + OCCURS_PTRN,
        FIELD_PTRN + PIC_PTRN,
        FIELD_PTRN
    ] ]
    FIELDS = ['occurs', 'level', 'name', 'type', 'length', 'decimal_pos', 'pic', 'comp']
    pic = PictureString()

    def parse(self, line_num, line):
        fields = { 'name': '', 'level': '0', 'occurs': '1', 'comp': '0' }
        pattern_num, num_patterns = 0, len(self.FIELD_RE)
        while pattern_num < num_patterns:
            match = self.FIELD_RE[pattern_num].match(line)
            if match:
                for key, value in match.groupdict().items():
                    fields[key] = value
                    #print fields[key]
                break
            pattern_num += 1
            #pattern_num -= 1
        result = [ fields[i] for i in self.FIELDS[:3] ]
        #print result
        if 'pic' in fields:
             result += self.pic.parse(fields['pic'], int(fields['comp']))
             #print result
        return result


class Copybook:

    LEGAL_DB_NAME_RE = re.compile(r'[^\w*+]')
    OCCURS, LEVEL, NAME = range(3)
    #csv_file = open('csv_file.csv','w+')

    def legalize_db_name(self, name, camel_case=False):
        name = self.LEGAL_DB_NAME_RE.sub('_', name)
        if camel_case:
            return ''.join([ i.capitalize() for i in name.split('_') ])
        return name.upper()

    def set2legal_db_names(self):
        result = []
        for field in self.fields:
            field = list(field)
            if len(field) <= 3:
                field[self.NAME] = self.legalize_db_name(field[self.NAME], True)
                if not field[self.OCCURS].isdigit():
                    field[self.OCCURS] = self.legalize_db_name(field[self.OCCURS])
            else:
                field[self.NAME] = self.legalize_db_name(field[self.NAME])
            result.append(field)
        self.fields = result

    def occurs_n_times(self):
        levels = [0]
        for field in self.fields:
            line = ''
           #print field
            level = int(field[self.LEVEL])
            if level == 1:
                line = field[self.NAME]
            if level <= (levels[0]-1):
                levels.pop()
            tabs = '\t' * (len(levels) - 1)
            if len(field) > 3:
                line = ', '.join([ str(i) for i in field[self.NAME:] ])
                #print len(field)
            elif field[self.OCCURS] != '1':
                line = '{0[2]} OCCURS {0[0]!r} TIMES:'.format(field)
                levels.append(level)
            if line:
                writer=csv.writer(csv_file1,delimiter=',')
                writer.writerow(line)
                #sys.stdout.write(tabs + line + '\n')

    def parse(self, lines):
        lines = [ i.strip() for i in lines ]
        lines = [ i for i in lines if i ]
        lines = [ i for i in lines if i[0] != '*' ]
        field = Field()
        self.fields = [ field.parse(i, j) for i, j in enumerate(lines) ]
        self.set2legal_db_names()
        self.occurs_n_times()


    def camel_case(self, name):
        return ''.join([ i.title() for i in name.split('_') ])


def main(args):
    Copybook().parse(args.copybook.readlines())

if __name__ == '__main__':
    from cmd_line_args import Args


    args = Args(USAGE, __version__)
    args.allow_stdin()
    args.add_files('copybook')
    main(args.parse())

答案 2 :(得分:-2)

我可以输入所有答案或发送给我学到的地方。 :)

检查一下,它确切地解释了你想要做的事情。

http://www.codeproject.com/Articles/300785/Calculating-simple-running-totals-in-SQL-Server