2013-12-23 2 views
7

Используя следующую таблицу,Выберите строку из первых ненулевых значений в разреженной таблице

A| B| C 
----------- 
1|null|null 
4|null|null 
4| 9|null 
5| 1| 7 

Как выбрать первое ненулевое значение каждого столбца в рабочем окне N строк? Например. запрашивая таблицу выше приведет:

A| B| C 
----------- 
1| 9| 7 
+0

«первый» imples заказ к столу, есть столбец на заказ на? –

+0

@ PetterEngström Да, должен быть * заказ *, может быть что угодно. В моем случае это поле метки времени. –

+0

@AlexB Колонка, которую вы заказываете, должна быть частью вашей таблицы примеров. SQL-запросы не дают результатов в каком-либо конкретном порядке, если SQL-запрос не запрашивает порядок явно. – Oswald

ответ

0

Не уверен, что, если я получил вопрос правильно
, как это кажется довольно простой в принципе.
Попробуйте этот запрос.

SQL Скрипка: http://sqlfiddle.com/#!11/ac585/8

WITH t0 AS 
(
    SELECT A FROM 
    TableName t0 
    WHERE (A IS NOT NULL) 
    ORDER BY ID ASC 
    LIMIT 1 
), 

t1 AS 
(
    SELECT B FROM 
    TableName 
    WHERE (B IS NOT NULL) 
    ORDER BY ID ASC 
    LIMIT 1 
), 

t2 AS 

(
    SELECT C FROM 
    TableName 
    WHERE (C IS NOT NULL) 
    ORDER BY ID ASC 
    LIMIT 1 
) 

SELECT t0.A, t1.B, t2.C 
FROM 
t0 
JOIN t1 ON 1=1 
JOIN t2 ON 1=1 
3

Вы должны определить порядок (первичный ключ или что-то еще), чтобы получить первое не пустое значение. Поэтому я использовал столбец ID для упорядочивания строк в таблице.

select 
(select A from t where A is not null ORDER BY id LIMIT 1), 
(select b from t where b is not null ORDER BY id LIMIT 1), 
(select c from t where c is not null ORDER BY id LIMIT 1) 

SQLFiddle demo

1

Вы можете сделать это с window functions. Я Разделенный результат в 2-х частей, а затем использовал этот раздел для row_numberwindow function

  1. , имеющих нулевых значений
  2. иметь действительный действительный

Затем, используя основной case, чтобы получить те, имеющие row_number, как 1 и которые имеют значение в них not null

SQLFIDDLE

SELECT 
    max (CASE 
      WHEN a_row_num = 1 AND a IS NOT NULL THEN a 
      END) AS A, 
    max (CASE 
      WHEN b_row_num = 1 AND B IS NOT NULL THEN B 
      END) AS B, 
    max (CASE 
      WHEN c_row_num = 1 AND C IS NOT NULL THEN C 
      END) AS C 
FROM 
    (
     SELECT 
      a, 
      row_number () over (partition BY a IS NULL ORDER BY ID) a_row_num, 
      b, 
      row_number () over (partition BY b IS NULL ORDER BY ID) b_row_num, 
      c, 
      row_number () over (partition BY c IS NULL ORDER BY ID) c_row_num 
     FROM 
      test 
    ) AS sub_query 

Выход:

| A | B | C | 
|---|---|---| 
| 1 | 9 | 7 | 

Примечание: Я добавил id поле, которое помогает узнать, какие из записей первым был введен, мы используем его в порядке возрастания в нашей оконной функции

7

функция окна first_value() позволяет довольно короткое и элегантное решение:

SELECT first_value(a) OVER (ORDER BY a IS NULL, ts) AS a 
    , first_value(b) OVER (ORDER BY b IS NULL, ts) AS b 
    , first_value(c) OVER (ORDER BY c IS NULL, ts) AS c 
FROM t 
LIMIT 1; 

a IS NULL - TRUE/FALSE. FALSE (0) вид перед тем TRUE (1). Таким образом, сначала принимаются ненулевые значения. Закажите по ts (колонка с меткой времени, как вы прокомментировали), и у вас ее есть в одном SELECT.

SQL Fiddle.

+1

этот id лучший ответ, я думаю, использовал и помог. Фокус на 'a IS NULL' -' BOOLEAN'. не сам по себе – Saidolim

Смежные вопросы