#sql #oracle #pivot #aggregate-functions
#sql #Oracle #сводная #агрегатные функции
Вопрос:
У меня есть таблица, подобная этой:
Id Date1 Date2 Status
----------------------------------------------
1 01/01/2010 null A
2 04/04/2010 05/14/10 X
3 01/01/2010 null A
4 01/11/2010 01/01/2010 X
5 01/02/2010 null A
И несколько других записей, Дата 1 не равна null, но она актуальна только в группе by, если статус равен A, для записей, где Date2 не равен null, независимо от статуса, которым должна быть группа by по этой Дате2.
Желаемый набор результатов выглядит следующим образом:
Date Number of A Status Number of Date 2 not null statuses
------------------------------------------------------------------------------
01//01/2010 2 1
01/02/2010 1 0
05/14/2010 0 1
В принципе, group by должна группироваться по дате, проблема в том, что в некоторых случаях это относится к столбцу Date1, а в другом случае — к столбцам Date2. Как это может быть достигнуто?
Комментарии:
1. Это для Oracle, но должно быть таким же для SQL
2. То, что вы думаете, не всегда так — SQL расшифровывается как «Структурированный язык запросов», а не «Стандартизированный». Хотя ANSI улучшает это, функциональность ANSI не обязательно выполняется так быстро, как собственный синтаксис.
Ответ №1:
Вы можете сгруппировать по выражению decode или case. Пробовал только в Oracle, поэтому не уверен, что это переносимо. С помощью этих данных:
create table t42 as
select 1 id, to_date('01/01/2010') date1, null date2, 'A' status from dual
union select 2, to_date('04/04/2010'), to_date('05/14/2010'), 'X' from dual
union select 3, to_date('01/01/2010'), null, 'A' from dual
union select 4, to_date('01/11/2010'), to_date('01/01/2010'), 'X' from dual
union select 5, to_date('01/02/2010'), null, 'A' from dual
/
select * from t42;
ID DATE1 DATE2 STATUS
---------------------- ------------------------- ------------------------- ------
1 01/01/2010 A
2 04/04/2010 05/14/2010 X
3 01/01/2010 A
4 01/11/2010 01/01/2010 X
5 01/02/2010 A
Вы можете сделать:
select case when date2 is null and status = 'A' then date1
else date2 end as "Date",
sum(case when status = 'A' then 1 else 0 end) as "Number of A status",
sum(case when date2 is null then 0 else 1 end) as "Number of Date 2 null"
from t42
group by case when date2 is null and status = 'A' then date1 else date2 end
order by 1;
Который дает:
Date Number of A status Number of Date 2 null
------------------------- ---------------------- ----------------------
01/01/2010 2 1
01/02/2010 1 0
05/14/2010 0 1
Ответ №2:
Это типичный СВОДНЫЙ запрос:
SELECT x.date,
SUM(CASE WHEN 'A' IN (y.status, z.status) THEN 1 ELSE 0 END) AS NumStatusA,
SUM(CASE
WHEN y.date2 IS NOT NULL OR z.date2 IS NOT NULL THEN 1
ELSE 0
END) AS NumDate2NotNull
FROM (SELECT a.date1 AS date
FROM YOUR_TABLE a
UNION
SELECT b.date2 AS date
FROM YOUR_TABLE b) x
LEFT JOIN YOUR_TABLE y ON y.date1 = x.date
LEFT JOIN YOUR_TABLE z ON z.date1 = x.date
GROUP BY x.date
Но вам нужно вывести таблицу, содержащую даты из обоих столбцов, на основе ваших данных, чтобы сначала объединить их.
Комментарии:
1. Это группирует только по дате1. Он спрашивает, как сгруппировать по 2 разным столбцам даты.
2. Вам нужно исправить ОБЪЕДИНЕНИЕ — оно должно выбираться из date1 или date2 в зависимости, не так ли?
Ответ №3:
Может быть, что-то вроде этого:
SELECT DISTINCT Date1 as Date,
(SELECT COUNT(*) FROM MyTable WHERE DATE1=MyT.Date1 AND Status = 'A') NumberAStatus,
(SELECT COUNT(*) FROM MyTable WHERE DATE1=MyT.Date1 AND Date2 is not null) NotNullDate2
FROM MyTable MyT
Комментарии:
1. Это группирует только по Date1 — он хочет сгруппировать по Date1 и Date2.