Convert query PIVOT from Oracle to SQL Server error - sql

Currently I am converting the an Oracle trigger to SQL Server, but I run into a problem.
My query in Oracle is like this
SELECT
CUSTOMER_ID, NVL(MATRIX1,0) MATRIX1, NVL(MATRIX2,0) MATRIX2
FROM
(SELECT DISTINCT
CUSTOMER_ID, SCORE
FROM STABLE) A
PIVOT (SUM(1) AS SCORE_MATRIX FOR (SCORE) IN (
1 AS IND_1, 2 AS IND_2));
My T-SQL query in SQL Server looks like this
SELECT
CUSTOMER_ID, ISNULL(MATRIX1,0) AS MATRIX1, ISNULL(MATRIX2,0) AS MATRIX2
FROM
(SELECT DISTINCT
CUSTOMER_ID, SCORE
FROM STABLE) A
PIVOT (SUM(1) AS SCORE_MATRIX FOR (SCORE) IN (
1 AS IND_1, 2 AS IND_2)) PVT;
However I get an error:
Msg 102, Level 15, State 1, Line 18
Incorrect syntax near '1'.
I could not figure out why for this error, so could anyone help identify? Thank you very much!

The error comes from the SUM(1).
Since 1 is not a column in the source query A.
Also, on sql-server those alias names within the PIVOT declaration aren't allowed like on Oracle.
So with a few fixes the PIVOT will work on sql-server.
SELECT
CUSTOMER_ID, ISNULL([1],0) AS MATRIX1, ISNULL([2],0) AS MATRIX2
FROM
(SELECT DISTINCT CUSTOMER_ID, SCORE FROM STABLE) AS A
PIVOT (
COUNT(SCORE) FOR SCORE IN ([1], [2])
) AS PVT;
Notes:
SUM(1) was replaced by COUNT(SCORE).
And that COUNT(SCORE) will give either 1 or NULL in that PIVOT for SCORE.
So this will also result in a matrix filled with 0 a 1.

Related

Single Oracle SQL query with CTE produces "SELECT list inconsistent with GROUP BY" error

I've got an Oracle query (unfortunately, I don't know DBMS version) that needs to return only one row of data. Also, it needs to be a single SELECT query, so temporary tables and parameters declarations are not allowed.
First, I'm using a CTE which aggregates values on all columns except the first, which is used as a GROUP BY condition. I need to display all those values in a single row, which works (I'm using 3 CROSS JOINs on filtered CTE, joining three one-row datasets, resulting in also a one-row dataset).
If I run only the CTE (not the whole CTE, just the SELECT in it), it works and produces no error. But if I wrap this SELECT statement in WITH ... AS construct, I'm given the error - Oracle SQL Developer.
Here is the CTE:
WITH
FRUITDATASET AS (
SELECT
-- FROM HERE, ORACLE SQL DEVELOPER MARKS LINES AS ERRONEOUS
FRUITTYPE,
COUNT(LONDONFRESH) AS LONDONFRESH,
COUNT(BERLINFRESH) AS BERLINFRESH,
SUM(0) AS LONDONSTALE,
SUM(0) AS BERLINSTALE
-- FROM HERE, THE QUERY IS VALID AGAIN
FROM
[...]
GROUP BY
FRUITTYPE
UNION ALL
SELECT
-- FROM HERE, THE ERROR HAPPENS AGAIN
FRUITTYPE,
SUM(0) AS LONDONFRESH,
SUM(0) AS BERLINFRESH,
COUNT(LONDONSTALE) AS LONDONSTALE,
COUNT(BERLINSTALE) AS BERLINSTALE
-- FROM HERE IT'S OKAY
FROM
[...]
GROUP BY
FRUITTYPE
)
Here is how I use the CTE:
SELECT
SUM(APPLES.LONDONFRESH) AS LONDONFRESHAPPLES,
SUM(APPLES.BERLINFRESH) AS BERLINFRESHAPPLES,
SUM(APPLES.LONDONSTALE) AS LONDONSTALEAPPLES,
SUM(APPLES.BERLINSTALE) AS BERLINSTALEAPPLES,
SUM(GRAPES.LONDONFRESH) AS LONDONFRESHGRAPES,
SUM(GRAPES.BERLINFRESH) AS BERLINFRESHGRAPES,
SUM(GRAPES.LONDONSTALE) AS LONDONSTALEGRAPES,
SUM(GRAPES.BERLINSTALE) AS BERLINSTALEGRAPES
FROM
DUAL
CROSS JOIN FRUITDATASET APPLES
ON APPLES.FRUITTYPE = 'APPLE'
CROSS JOIN FRUITDATASET GRAPES
ON GRAPES.FRUITTYPE = 'GRAPE'
Query runs anyway when I run it from SQL Developer, but if I put it into a report, it throws an exception. I've tried putting
NULL AS LONDONFRESH
[...]
GROUP BY
FRUITTYPE,
NULL
but it still doesn't work. Can you guys help me find out what's wrong with this query?
EDIT:
I think I probably solved this by using analytic functions:
WITH
FRUITDATASET AS (
SELECT
*
FROM (
SELECT
DISTINCT FRUITTYPE,
COUNT(LONDONFRESH) OVER(PARTITION BY FRUITTYPE) AS LONDONFRESH,
COUNT(BERLINFRESH) OVER(PARTITION BY FRUITTYPE) AS BERLINFRESH,
SUM(NULL) OVER(PARTITION BY FRUITTYPE) AS LONDONSTALE,
SUM(NULL) OVER(PARTITION BY FRUITTYPE) AS BERLINSTALE
FROM
[...]
)
UNION ALL
SELECT
*
FROM (
SELECT
DISTINCT FRUITTYPE,
SUM(NULL) OVER(PARTITION BY FRUITTYPE) AS LONDONFRESH,
SUM(NULL) OVER(PARTITION BY FRUITTYPE) AS BERLINFRESH,
COUNT(LONDONSTALE) OVER(PARTITION BY FRUITTYPE) AS LONDONSTALE,
COUNT(BERLINSTALE) OVER(PARTITION BY FRUITTYPE) AS BERLINSTALE
FROM
[...]
)
)
Right now I'm unable to check this solution on the server, but I'll post an answer as soon as I find out.
Apparently wrapping CTE into SELECT * FROM does the trick. Everything is working now.

Using SQL generate pivot table

i'm trying to learn using SQL to generate pivot table. But no matter how i try i keep getting ORA-00936: missing expression error from oracle.
Here is my query:
SELECT * FROM (SELECT HOS_PAY_ID, AMOUNT FROM HOSPITAL_PAYMENT)
PIVOT (SUM (AMOUNT) FOR AMOUNT IN ([10000],[8000],[7000],[9000],[11000],[13000]) AS TEST
ORDER BY HOS_PAY_ID;
and this is my data:
Thank You.
Try this
SELECT * FROM
(
SELECT HOS_PAY_ID, AMOUNT
FROM HOSPITAL_PAYMENT
)
PIVOT (
SUM (AMOUNT) FOR AMOUNT IN (10000,8000,7000,9000,11000,13000)
)
ORDER BY HOS_PAY_ID;

materialized view using WITH statement

i created a materialized view but i have a mistake i do not understand to resolve it
RA-00937: not a single-group group function
00937. 00000 - "not a single-group group function
on line
SELECT x.*,SUM(x.quantities) as Tquantities
can you help me to resolve it
CREATE MATERIALIZED VIEW TestView AS
With x AS(
SELECT Numclient as CLIENT,
Numcommand as COMMAND,
count(gender) as quantities
FROM customer,
Command
WHERE Numclient = Numcommand
AND gender =2
GROUP BY Numclient,
Numcommand
),
x1 AS (
SELECT x.*,SUM(x.quantities) as Tquantities
FROM x
)
SELECT x.*,ROUND(x.quantities*100/x1.Tquantities) as Percent
FROM x1, x;
In order to eliminate error remove x.*, in your original subquery x1.
Your select statement can be simplified, like here:
select Numclient CLIENT, Numcommand COMMAND, count(gender) quantities,
round(100*count(gender)/sum(count(gender)) over()) percent
from customer
join Command on Numclient = Numcommand and gender = 2
group by Numclient, Numcommand
SQLFiddle
It's little unclear why are you displaying column COMMAND, when it's equal to CLIENT?
I suspect that maybe this is mistake in where condition or this column is superfluous.
Since when is this valid in Oracle? This is not MySQL.
SELECT x.*,SUM(x.quantities) as Tquantities FROM x
In order to this to work, you have to GROUP BY the columns in x.

find every 5th record from table

There are n record in a table ABC .
write a query to select every 5th record from the table.
for example there are 30 rows in a table.
so query should output 5th,10th,15th,20th, 25th and 30th record from the table.
I tried ROW_NUMBER OVER (ORDER BY id ) but getting msg :-
Message from SQL server IML (msg 156, level 15, state 2):
Incorrect syntax near the keyword 'OVER'.
I am using Sybase database.
You need to define order to get every 5th row. It can be for example PRIMARY KEY ID or something like this
select * from
(
select ABC.*, ROW_NUMBER() OVER (ORDER BY id) as RN from ABC
) t1
where RN % 5 = 0
This is not how SQL works. I'm not sure which column would give you what you want, but you aren't supposed to know or care about how the data is stored or what the ordering might be.
You need to figure out a WHERE clause that gives you what you want. Something depending on order is wrong.
try this
select rn, col_list from (select rownum rn, col_list from tab_name)
where rn=N;
where N is the row number you want.
Try this way.
Create temporary table with identity column.
select
id = identity(8),
column1,....
into #ABC
from ABC
Select with modulo:
select * from #ABC
where id % 5 = 0

How do write the following sql fragment for SQL Server 2000

Can Someone please help to how to write the below code in SQL Server2000? Thanks
WITH cte
AS (SELECT *,
( Row_number() OVER(ORDER BY productid, transactionid,
statusdate
DESC)
)AS
rownum
FROM #table),
cte2
AS (SELECT cte.*,
( CASE
WHEN cte.status = Isnull((SELECT t.status
FROM cte t
WHERE t.rownum = ( cte.rownum + 1
)),
'')
THEN 1
ELSE 0
END )AS rownum2
FROM cte)
SELECT cte2.productid,
cte2.transactionid,
cte2.details,
cte2.status,
cte2.statusdate,
cte2.requestdate
FROM cte2
WHERE rownum2 = 0
There is no OVER() function in 2000, so you will need to re-address/move the initial cte select. You already have a table variable #table, so I would modify this to include the row numbers, by adding a identity column.
You could then use a subquery to extract what you need from cte2.
DigbySwift's answer mentions that there is a problem with ROW_NUMBER and you need to solve that first. You can use the idea in his answer, and you could also look at answers to similar questions such as these:
ROW_NUMBER Alternative for SQL Server 2000
Row_Number simulation in Sql server 2000
However there's also another problem: SQL Server 2000 doesn't support CTEs (WITH ... AS ...).
To solve this use subselects instead of CTEs by removing the WITH clause and moving the definition of the CTE to the place(s) where it is used.
For example this query using CTEs:
WITH T1 AS (SELECT a,b,c FROM ...)
SELECT * FROM T1
Becomes:
SELECT *
FROM (
SELECT a,b,c FROM ...
) AS T1
Hopefully that is enough to get you started.