Соединение с одним и тем же столом дважды с разными условиями

Языки регексов недостаточно эффективны для сопоставления произвольно вложенных конструкций. Для этого вам нужен пусковой автомат (т. Е. Синтаксический анализатор). Доступно несколько таких инструментов, таких как PLY .

Python также предоставляет библиотеку синтаксиса для своего собственного синтаксиса, который может делать то, что вам нужно. Выход очень подробный, однако, и занимает некоторое время, чтобы обернуть голову. Если вы заинтересованы в этом угле, следующее обсуждение пытается объяснить все как можно проще.

>>> import parser, pprint
>>> pprint.pprint(parser.st2list(parser.expr('(((1+0)+1)+1)')))
[258,
 [327,
  [304,
   [305,
    [306,
     [307,
      [308,
       [310,
        [311,
         [312,
          [313,
           [314,
            [315,
             [316,
              [317,
               [318,
                [7, '('],
                [320,
                 [304,
                  [305,
                   [306,
                    [307,
                     [308,
                      [310,
                       [311,
                        [312,
                         [313,
                          [314,
                           [315,
                            [316,
                             [317,
                              [318,
                               [7, '('],
                               [320,
                                [304,
                                 [305,
                                  [306,
                                   [307,
                                    [308,
                                     [310,
                                      [311,
                                       [312,
                                        [313,
                                         [314,
                                          [315,
                                           [316,
                                            [317,
                                             [318,
                                              [7,
                                               '('],
                                              [320,
                                               [304,
                                                [305,
                                                 [306,
                                                  [307,
                                                   [308,
                                                    [310,
                                                     [311,
                                                      [312,
                                                       [313,
                                                        [314,
                                                         [315,
                                                          [316,
                                                           [317,
                                                            [318,
                                                             [2,
                                                              '1']]]]],
                                                         [14,
                                                          '+'],
                                                         [315,
                                                          [316,
                                                           [317,
                                                            [318,
                                                             [2,
                                                              '0']]]]]]]]]]]]]]]],
                                              [8,
                                               ')']]]]],
                                          [14,
                                           '+'],
                                          [315,
                                           [316,
                                            [317,
                                             [318,
                                              [2,
                                               '1']]]]]]]]]]]]]]]],
                               [8, ')']]]]],
                           [14, '+'],
                           [315,
                            [316,
                             [317,
                              [318, [2, '1']]]]]]]]]]]]]]]],
                [8, ')']]]]]]]]]]]]]]]],
 [4, ''],
 [0, '']]

Вы можете облегчить боль этой короткой функцией:

def shallow(ast):
    if not isinstance(ast, list): return ast
    if len(ast) == 2: return shallow(ast[1])
    return [ast[0]] + [shallow(a) for a in ast[1:]]

>>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)'))))
[258,
 [318,
  '(',
  [314,
   [318, '(', [314, [318, '(', [314, '1', '+', '0'], ')'], '+', '1'], ')'],
   '+',
   '1'],
  ')'],
 '',
 '']

Числа поступают из модулей Python symbol и token, которые вы можете использовать для построения таблицы поиска из чисел в имена:

map = dict(token.tok_name.items() + symbol.sym_name.items())

Вы даже можете свернуть это сопоставление в shallow(), чтобы вы могли работать со строками вместо чисел:

def shallow(ast):
    if not isinstance(ast, list): return ast
    if len(ast) == 2: return shallow(ast[1])
    return [map[ast[0]]] + [shallow(a) for a in ast[1:]]

>>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)'))))
['eval_input',
 ['atom',
  '(',
  ['arith_expr',
   ['atom',
    '(',
    ['arith_expr',
     ['atom', '(', ['arith_expr', '1', '+', '0'], ')'],
     '+',
     '1'],
    ')'],
   '+',
   '1'],
  ')'],
 '',
 '']

1
задан GMB 28 February 2019 в 22:33
поделиться

1 ответ

Ваш запрос пока выглядит хорошо. Чтобы проверить, использует ли продукт клиент впервые, вы можете использовать ROW_NUMBER(), чтобы присвоить ранг каждой записи в группах записей с одинаковым UserId и одинаковым Product, упорядоченных по Date. Когда номер строки 1, вы знаете, что имеете дело с новым продуктом.

SELECT 
    UA.UserId, 
    UA.Product, 
    UA.Client, 
    CASE 
        WHEN ROW_NUMBER() OVER(PARTITION BY UA.UserId, UA.Product ORDER BY UA.Date) = 1 
        THEN true 
        ELSE false 
    END AS IsNewProduct,
    CASE 
        WHEN UA.Date = FLS.Date
        THEN true
        ELSE false
    END AS IsNewClient
FROM UserActivity as UA
LEFT JOIN FirstLastSeen AS FLS 
    ON UA.UserId   = FLS.UserId 
    AND UA.Product = FLS.Product 
    AND UA.Client  = FLS.Client;

Эта демонстрация на DB Fiddle с вашими примерами возвращает:

| UserId | Product | Client      | IsNewProduct | IsNewClient |
| ------ | ------- | ----------- | ------------ | ----------- |
| John   | Bank    | Mobile App  | 1            | 0           |
| John   | Bank    | Desktop App | 0            | 1           |
| Sally  | Gym     | Web App     | 1            | 1           |
0
ответ дан GMB 28 February 2019 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: