#sql #oracle #pivot
#sql #Oracle #сводная
Вопрос:
У меня есть такая таблица:
NAME VALUE IDENTIFIER MYDATE
NAME1 123 ATR 01/10/2018
NAME1 333 QTDE 01/10/2018
NAME2 212 ATR 01/08/2018
NAME2 123 QTDE 01/08/2018
NAME2 133 ATR 01/09/2018
NAME2 123 QTDE 01/09/2018
NAME3 678 ATR 01/08/2018
NAME3 123 QTDE 01/08/2018
В IDENTIFIER
, это будет только ATR
или QTDE
.
Мне нужно сделать сводку, чтобы получить VALUE
от QTDE
или ATR
за каждый месяц, чтобы результат был примерно таким
NAME QTDE08/2018 ATR08/2018 QTDE09/2018 ATR09/2018 QTDE10/2018 ATR10/2018
NAME1 0 0 0 0 333 123
NAME2 123 212 123 133 0 0
NAME3 123 678 0 0 0 0
Я пытался сделать сводку, но я мог обойтись только с IDENTIFIER
, и я понятия не имею, как сделать это и с датой
SELECT *
FROM (SELECT ST.NAME,
ST.VALUE,
ST.IDENTIFIER,
TO_CHAR(TO_DATE(ST.MYDATE), 'MM/YYYY') AS MYDATE
FROM SOME_TABLE ST
WHERE ST.IDENTIFIER IN ('QTDE', 'ATR'))
PIVOT(SUM(VALUE)
FOR IDENTIFIER IN ('QTDE' AS QTDE,
'ATR' AS ATR))
Я редактирую имя таблицы и colunms, оно не является оригинальным из моей таблицы.
Комментарии:
1. Вы не можете. Кажется, вы хотите, чтобы даты (или, по крайней мере, их
'MM/YYYY'
представление) исходили из данных, а не были жестко запрограммированы в запросе заранее. Это называется «динамическим поворотом», это можно сделать, но не в обычном SQL, и, как правило, это плохая практика. ЗАЧЕМ вам нужен вывод в этом формате? Если это просто для отчетности, вам может быть лучше использовать приложение для создания отчетов, которое имеет возможность выполнять такую динамическую сводку в приложении.2. @mathguy вы сказали
You can't
и послеThis is called "dynamic pivoting", it can be done
. Я не понимаю. А также, да, это для отчетности.3. «Вы не можете», как в «вы не можете так, как вы просите», то есть в стандартном
SELECT
запросе. «Это можно сделать», но » вы не можете этого сделать» (в любом случае, я сомневаюсь, что вы можете.) Имеет ли это смысл?4. Это невозможно сделать в SQL, но я могу сделать это в приложении отчетности? Кстати, я использую telerik
5. Я не знаком с telerik (и вообще с приложениями для создания отчетов в целом); Я считаю, что их код обычно является проприетарным, но нетрудно догадаться, что они, вероятно, используют динамический SQL под капотом. Дело в том, что гораздо проще научиться «делать» динамическую сводку с помощью функций приложения, чем изучать динамический SQL и писать код самостоятельно, с нуля. Узнайте, какие возможности поворота могут быть у telerik.
Ответ №1:
Вы пытаетесь преобразовать 2 столбца date и identifier, поэтому вам нужно 2 сводки. Пожалуйста, попробуйте выполнить запрос ниже, он должен работать. Не стесняйтесь возвращаться в случае каких-либо запросов. Это работает в oracle, но не уверен, пытаетесь ли вы использовать какую-либо другую СУБД.
select * from (
select * from (
with all_data as
(select 'NAME1' fname, 123 value, 'ATR' identif, '01-OCT-2018' mydate from dual union all
select 'NAME1' fname, 333 value, 'QTDE' identif, '01-OCT-2018' mydate from dual union all
select 'NAME2' fname, 212 value, 'ATR' identif, '01-AUG-2018' mydate from dual union all
select 'NAME2' fname, 123 value, 'QTDE' identif, '01-AUG-2018' mydate from dual union all
select 'NAME2' fname, 133 value, 'ATR' identif, '01-SEP-2018' mydate from dual union all
select 'NAME2' fname, 123 value, 'QTDE' identif, '01-SEP-2018' mydate from dual union all
select 'NAME3' fname, 678 value, 'ATR' identif, '01-AUG-2018' mydate from dual union all
select 'NAME3' fname, 123 value, 'QTDE' identif, '01-AUG-2018' mydate from dual )
select identif,fname,value,mydate from all_data)
pivot
(
sum(value)
for mydate in ('01-AUG-2018' as "AUG-2018",'01-SEP-2018' as "SEP-2018",'01-OCT-2018' as "OCT-2018")))
pivot
(
sum("AUG-2018") "08-2018"
,sum("SEP-2018") "09-2018"
,sum("OCT-2018") "10-2018"
for identif in ('ATR' ATR,'QTDE' QTDE))
order by 1;
Комментарии:
1. с вашим ответом мне нужно было бы перечислить все дни и все годы, чтобы заставить его работать, и каждый месяц мне нужно было бы добавлять новые строки в код, чтобы охватить все годы. Это не ответ на эту проблему, я не могу создать тысячи строк, чтобы охватить все возможные даты
2. Пожалуйста, используйте динамический sql для ввода дат и определения значений.
3. Как использовать динамический sql? У меня нет идеи, пожалуйста, объясните @sudheer
Ответ №2:
приведенный ниже пример должен быть переписан в Oracle и соответствовать требованиям ur.
CREATE TABLE Project(PRJ_ID int, UDN_ID INT, TXT_VALUE varchar(100));
INSERT INTO Project VALUES (8344,82,'E S'),(8344,69,'A M'),(8364,82,'End'),(8364,59,'Internal');
DECLARE @columns NVARCHAR(MAX), @columns1 NVARCHAR(MAX), @sql NVARCHAR(MAX);
--selecting distinct values and concatenating to get a result like [82],[69],[82]...
SELECT @columns1 = STUFF((
SELECT DISTINCT ',' '[' CAST(UDN_ID AS VARCHAR) ']' FROM Project
FOR XML PATH('')
), 1, 1, '')
FROM Project;
--using that dynamic column string in the pivot query string
SET @sql = 'SELECT PRJ_ID,' @columns1 ' FROM
(
SELECT * FROM Project
) AS src
PIVOT
(
MAX(TXT_VALUE) FOR src.UDN_ID IN (' @columns1
')
) AS p;';
--executing the pivot query
EXEC sp_executesql @sql;
Комментарии:
1. Этот ответ не имеет ничего общего с вопросом, пожалуйста, приведите и пример, связанный с вопросом