Выбирает все строки (и столбцы), где одно значение в столбце является самым высоким - PullRequest
1 голос
/ 22 апреля 2020

У меня есть таблица в следующей форме:

index, ingestion_id,        a,  b,  c,  d

0,     '2020-04-22-1600',   0a, 0b, 0c, 0d
1,     '2020-04-22-1700',   0a, 0b, 0c, 0d
2,     '2020-04-22-1600',   1a, 1b, 1c, 1d
3,     '2020-04-22-1700',   1a, 1b, 1c, 1d
4,     '2020-04-22-1800',   1a, 1b, 1c, 1d
...

Я хотел бы извлечь все строки и столбцы, где ingestion_id является самым высоким. Таким образом, он должен возвращать индекс 1 и индекс 4 для всех строк и столбцов.

Я нашел несколько примеров, но они требуют, чтобы мы предварительно определили столбцы , которые мы хотим выбрать. Я не знаю столбцы заранее, но я знаю, что таблица будет иметь столбец с именем ingestion_id. Вот пример :

SELECT *
    FROM (
        SELECT MAX(ingestion_id) as ingestion_id, a, b, c, d
        FROM table as t
        GROUP BY a, b, c, d
        ORDER BY a
    )

Как выбрать все столбцы, где ingestion_id является самым высоким, и сгруппировать по всем столбцам, кроме ingestion_id?


БОНУС

Представьте себе таблицу, теперь имеющую форму:

index, ingestion_id,        a,  b,  c,  d

0,     '2020-04-22-1600',   0a, 0b, 0c, 0d
1,     '2020-04-22-1700',   0a, 0b, 0c, 0d
2,     '2020-04-22-1600',   1a, 1b, 1c, 1d
3,     '2020-04-22-1700',   1a, 1b, 1c, 1d
4,     '2020-04-26-1800',   2a, 2b, 2c, 2d
5,     '2020-04-26-1900',   2a, 2b, 2c, 2d
...

Ответ , предоставленный Гордоном Линоффом (по состоянию на 2020/04 год / 26) в этом случае отфильтровывает только строку 5, поскольку она является самой высокой ingestion_id. Однако нам также понадобится строка 1 и строка 3, поскольку значения (за исключением столбца ingestion_id) являются уникальными в других столбцах.

Ответы [ 5 ]

4 голосов
/ 22 апреля 2020

Это отвечает на оригинальную версию вопроса.

Я хотел бы извлечь все строки и столбцы, где ingestion_id является самым высоким.

Если я правильно понимаю, вы можете использовать в окне функции:

select t.* except (seqnum)
from (select t.*, rank() over (order by ingestion_id desc) as seqnum
      from `t` t
     ) t
where seqnum = 1;

Вы можете выбрать все соответствующие строки как:

select t.* except (seqnum, grpid, min_grpid_seqnum)
from (select t.*,
             min(seqnum) over (partition by grpid) as min_grpid_seqnum
      from (select t.*, rank() over (order by ingestion_id desc) as seqnum,
                   dense_rank() over (partition by a, b, c, d) as grpid
            from `t` t
           ) t
     ) t
where min_grpid_seqnum = 1;
2 голосов
/ 26 апреля 2020

Ниже для BigQuery Standard SQL

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 0 index, '2020-04-22-1600' ingestion_id, '0a' a, '0b' b, '0c'c, '0d' d UNION ALL
  SELECT 1, '2020-04-22-1700', '0a', '0b', '0c', '0d' UNION ALL
  SELECT 2, '2020-04-22-1600', '1a', '1b', '1c', '1d' UNION ALL
  SELECT 3, '2020-04-22-1700', '1a', '1b', '1c', '1d' UNION ALL
  SELECT 4, '2020-04-26-1800', '2a', '2b', '2c', '2d' UNION ALL
  SELECT 5, '2020-04-26-1900', '2a', '2b', '2c', '2d' 
)
SELECT ARRAY_AGG(t ORDER BY ingestion_id DESC LIMIT 1)[OFFSET(0)].*  
FROM `project.dataset.table` t
GROUP BY TO_JSON_STRING((SELECT AS STRUCT * EXCEPT(index, ingestion_id) FROM UNNEST([t])))

с выводом

Row index   ingestion_id        a       b       c       d    
1   1       2020-04-22-1700     0a      0b      0c      0d   
2   3       2020-04-22-1700     1a      1b      1c      1d   
3   5       2020-04-26-1900     2a      2b      2c      2d   
2 голосов
/ 22 апреля 2020

Как выбрать все столбцы, для которых ingestion_id является наибольшим, и сгруппировать по всем столбцам, кроме ingestion_id?
Каждый источник имеет различный набор столбцов с разными именами

Ниже для BigQuery Standard SQL и не имеет никакой зависимости от наименования для остальных столбцов вообще

#standardSQL
SELECT ARRAY_AGG(t ORDER BY ingestion_id DESC LIMIT 1)[OFFSET(0)].*  
FROM `project.dataset.table` t
GROUP BY TO_JSON_STRING((SELECT AS STRUCT * EXCEPT(ingestion_id) FROM UNNEST([t])))

Если применить к образцу данных из вашего вопроса, как показано ниже пример

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '2020-04-22-1600' ingestion_id, '0a' a, '0b' b, '0c'c, '0d' d UNION ALL
  SELECT '2020-04-22-1700', '0a', '0b', '0c', '0d' UNION ALL
  SELECT '2020-04-22-1600', '1a', '1b', '1c', '1d' UNION ALL
  SELECT '2020-04-22-1700', '1a', '1b', '1c', '1d' UNION ALL
  SELECT '2020-04-22-1800', '1a', '1b', '1c', '1d' 
)
SELECT ARRAY_AGG(t ORDER BY ingestion_id DESC LIMIT 1)[OFFSET(0)].*  
FROM `project.dataset.table` t
GROUP BY TO_JSON_STRING((SELECT AS STRUCT * EXCEPT(ingestion_id) FROM UNNEST([t])))

вывод

Row ingestion_id    a   b   c   d    
1   2020-04-22-1700 0a  0b  0c  0d   
2   2020-04-22-1800 1a  1b  1c  1d   
1 голос
/ 03 мая 2020

Это можно сделать в стандартном SQL следующим образом.

Я предполагаю, что ваши данные находятся во временной таблице.

WITH temp AS (SELECT 0 index, '2020- 04-22-1600 'ingestion_id,' 0a 'a,' 0b 'b,' 0 c 'c,' 0d 'd UNION ALL SELECT 1,' 2020-04-22-1700 ',' 0a ' , '0b', '0 c', '0d' UNION ALL SELECT 2, '2020-04-22-1600', '1a', '1b', '1 c', '1d' UNION ALL SELECT 3, '2020-04-22-1700', '1a', '1b', '1 c', '1d' UNION ALL SELECT 4, '2020-04-26-1800', '2a', «2b», «2 c», «2d» UNION ALL SELECT 5, «2020-04-26-1900», «2a», «2b», «2 c», «2d»)

выберите индекс, ingestion_id, a, b, c, d из (выберите индекс, ingestion_id, a, b, c, d, row_number () over (разбиение на a, b, c, d упорядочить ingestion_id des c) top from temp), где top = 1

Будет получен следующий вывод:

index ingestion_id ab c d
1 2020-04- 22-1700 0a 0b 0 c 0d
3 2020-04-22-1700 1a 1b 1 c 1d
5 2020-04-26-1900 2a 2b 2 c 2d

1 голос
/ 02 мая 2020

Вы запросили "все строки с наибольшим ingestion_id. Согласно вашим выборочным данным, у вас есть только одна строка значений с самым высоким значением для ingestion_id

Итак, по порядку чтобы представить ваши данные с самым высоким значением, вы можете использовать MAX() в подзапросе и просто использовать SELECT *, потому что вы не знаете всех столбцов, которые могут существовать, это будет выглядеть примерно так, в простейшем формате;

SELECT * FROM table
WHERE IngestionID = (SELECT MAX(IngestionID) FROM table);

Бонусный ответ

    DECLARE @columns NVARCHAR(MAX)
    DECLARE @result NVARCHAR(MAX)

 SELECT @columns = STUFF(
                        (

SELECT ',' + z.COLUMN_NAME FROM information_schema.columns z WHERE z.table_name = 'datatable'
AND z.COLUMN_NAME NOT IN ('Index_ID','Ingestion_ID') 
FOR xml path('')
)
                        , 1
                        , 1
                        , '')

SET @result = 'SELECT MAX(Ingestion_ID) [Ingestion ID],' + (SELECT @columns) + ' FROM datatable GROUP BY ' + (SELECT @columns);

EXEC(@result)

Примечание. Я изменил имя таблицы на datatable, чтобы избежать SQL зарезервированных ключевых слов (то же самое для индекса -> Index_ID)

Выходы

Ingestion ID    a   b   c   d
2020-04-22-1700 0a  0b  0c  0d
2020-04-22-1700 1a  1b  1c  1d
2020-04-26-1900 2a  2b  2c  2d

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

Проверено по следующим параметрам:

Column Name     DataType
Index_ID        int
Ingestion_ID    varchar(15)
a               varchar(2)
b               varchar(2)
c               varchar(2)
d               varchar(2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...