简体   繁体   中英

Convert SQL Server T-SQL to SQL

I have been trying out a code using pivot to get a certain view from a table .

create table temp
(
    date datetime,
    category varchar(3),
    amount money
)

insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('3/1/2012', 'ABC', 1100.00)


DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.category) 
            FROM temp c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT date, ' + @cols + ' from 
            (
                select date
                    , amount
                    , category
                from temp
           ) x
            pivot 
            (
                 max(amount)
                for category in (' + @cols + ')
            ) p '


execute(@query)

drop table temp

I get an error in the declare statement and also pivot is not being recognised as a keyword by dbviz SQL commander

I even removed the @ and tried to run it , I'm not able to execute successfuly

I'm using Oracle Database 11g ( oracle JDBC driver )

If you are trying to run this code from SQLPlus or SQLcl, you can use code below to generate the same information in Oracle.

Oracle 19c and later

In Oracle 19, Oracle introduce the ability to do LISTAGG(DISTINCT <value>) which removes the need to do a subquery to remove any duplicates.

CREATE TABLE temp
(
    date_val    DATE,
    category    VARCHAR (3),
    amount      NUMBER
);

INSERT INTO temp
     VALUES (DATE '2012-01-01', 'ABC', 1000.00);

INSERT INTO temp
     VALUES (DATE '2012-02-01', 'DEF', 500.00);

INSERT INTO temp
     VALUES (DATE '2012-02-01', 'GHI', 800.00);

INSERT INTO temp
     VALUES (DATE '2012-02-10', 'DEF', 700.00);

INSERT INTO temp
     VALUES (DATE '2012-03-01', 'ABC', 1100.00);

column category_list NEW_VALUE categories

SELECT '''' || LISTAGG (DISTINCT category, ''',''') WITHIN GROUP (ORDER BY category) || ''''    AS category_list
  FROM temp;

SELECT *
  FROM (SELECT date_val, amount, category FROM temp) x
       PIVOT (MAX (amount) FOR category IN (&categories)) p;

DROP TABLE temp;

Earlier than Oracle 19c

CREATE TABLE temp
(
    date_val    DATE,
    category    VARCHAR (3),
    amount      NUMBER
);

INSERT INTO temp
     VALUES (DATE '2012-01-01', 'ABC', 1000.00);

INSERT INTO temp
     VALUES (DATE '2012-02-01', 'DEF', 500.00);

INSERT INTO temp
     VALUES (DATE '2012-02-01', 'GHI', 800.00);

INSERT INTO temp
     VALUES (DATE '2012-02-10', 'DEF', 700.00);

INSERT INTO temp
     VALUES (DATE '2012-03-01', 'ABC', 1100.00);

column category_list NEW_VALUE categories

SELECT '''' || LISTAGG (category, ''',''') WITHIN GROUP (ORDER BY category) || ''''    AS category_list
  FROM (SELECT DISTINCT category
          FROM temp);

SELECT *
  FROM (SELECT date_val, amount, category FROM temp) x
       PIVOT (MAX (amount) FOR category IN (&categories)) p;

DROP TABLE temp;

Result from either script

SQL> @test_tsql_conversion.sql


Table TEMP created.


1 row inserted.


1 row inserted.


1 row inserted.


1 row inserted.


1 row inserted.


       CATEGORY_LIST
____________________
'ABC','DEF','GHI'


old:SELECT *
  FROM (SELECT date_val, amount, category FROM temp) x
       PIVOT (MAX (amount) FOR category IN (&categories)) p
new:SELECT *
  FROM (SELECT date_val, amount, category FROM temp) x
       PIVOT (MAX (amount) FOR category IN ('ABC','DEF','GHI')) p

    DATE_VAL    'ABC'    'DEF'    'GHI'
____________ ________ ________ ________
01-FEB-12                  500      800
10-FEB-12                  700
01-JAN-12        1000
01-MAR-12        1100


Table TEMP dropped.

Building on EJ Egyed's answer, here is a PL/SQL version:

declare
    cols   long;
    query  long;
    results sys_refcursor;
begin
    select '''' || listagg(category||''' as "'||upper(category)||'"', ', ''') within group (order by category)
    into   cols
    from   (select distinct category from temp);

    query :=
    'select * from 
     ( select dt, amount, category
       from temp ) x
     pivot 
     ( max(amount) for category in ('||cols||') ) p';

    open results for query;
    dbms_sql.return_result(results);
end;

The solution will vary depending on how you want to execute the code. dbms_sql.return_result will pass the result set to a 12c or later client such as SQL*Plus or SQL Developer, but might not work with third party tools such as DbVisualizer or Tableau. SQL*Plus is Oracle's basic command line tool used mostly for administration and deployment scripts, but not really suited for end user reporting. SQL Developer is a programmer's IDE, which a business analyst might use, but again it's not really for general end users.

The most generic approach might be to write this as a procedure that returns a refcursor, which could then be processed by an application written in Java, C# etc.

A procedure version would look like this:

create or replace procedure pivot_categories
    ( out_results out sys_refcursor )
as
    cols   long;
    query  long;
begin
    select '''' || listagg(category||''' as "'||upper(category)||'"', ', ''') within group (order by category)
    into   cols
    from   (select distinct category from temp);

    query :=
    'select * from 
     ( select dt, amount, category
       from temp ) x
     pivot 
     ( max(amount) for category in ('||cols||') ) p';

    open out_results for query;
end pivot_categories;

here is what you need:

create table temp
(
    date timestamp(3),
    category varchar2(3),
    amount number
);

insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('3/1/2012', 'ABC', 1100.00)


 v_cols NVARCHAR(MAX);
    v_query  NVARCHAR(MAX);

SELECT STUFF((SELECT distinct ',' || QUOTENAME(c.category) 
            FROM temp c
            FOR INTO v_cols FROM dual XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

v_query := 'SELECT date, ' || v_cols || ' from 
            (
                select date
                    , amount
                    , category
                from temp
           ) x
            pivot 
            (
                 max(amount)
                for category in (' || v_cols || ')
            ) p '


execute immediate v_query

drop table temp

also there is an online sql convert tool : http://www.sqlines.com/online

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM