NULL values returned by pivot - tsql

I have a dataset like the one below (first column created using ROW_NUMNBER OVER PARTITION):
RNEEAN NEEAN GFCUS SCSAC
NEAN1 9432806 94328 GE
NEAN2 9432807 94328 GE
NEAN3 94328472 94328 ES
NEAN4 9432848 94328 ES
NEAN5 9432875 94328 HK
NEAN6 9432876 94328 HK
NEAN7 9432877 94328 HK
NEAN8 9432878 94328 HK
NEAN9 9432879 94328 HK
I can get this dataset with the below query:
select RNEEAN, NEEAN, GFCUS, SCSAC from #tmp where GFCUS=094328
Now I want to pivot the column NEEAN by RNEEAN so I tried the below:
SELECT MAX([NEEAN1]) [NEEAN1],MAX([NEEAN2]) [NEEAN2],MAX([NEEAN3]) [NEEAN3],
MAX([NEEAN4]) [NEEAN4], MAX([NEEAN5]) [NEEAN5],MAX([NEEAN6]) [NEEAN6],MAX([NEEAN7] [NEEAN7], MAX([NEEAN8]) [NEEAN8], MAX([NEEAN9]) [NEEAN9], GFCUS
from #tmp
PIVOT(
min(NEEAN) for RNEEAN in ([NEEAN1],[NEEAN2],[NEEAN3],[NEEAN4],[NEEAN5],[NEEAN6], [NEEAN7],[NEEAN8],[NEEAN9])
) p1
where GFCUS=094328
GROUP BY GFCUS
But all I get is 9 NULL columns and the GFCUS value.
Where am I going wrong or missing something please?

The problem is with your RNEEAN names and then the column names you are using in the PIVOT.
The RNEEAN column contains data that starts with NEAN but then you are attempting to pivot values with a name of NEEAN - if the column names don't match then you will return null.
Using your data above, you'd have to use:
select GFCUS, SCSAC,
NEAN1, NEAN2, NEAN3, NEAN4, NEAN5, NEAN6, NEAN7, NEAN8, NEAN9
from
(
select RNEEAN, NEEAN, GFCUS, SCSAC
from yourtable
) d
pivot
(
min(NEEAN)
for RNEEAN IN (NEAN1, NEAN2, NEAN3, NEAN4, NEAN5, NEAN6, NEAN7, NEAN8, NEAN9)
) piv;
See Demo

Related

Converting rows to columns using crosstab in PostgreSQL not working (relation “table” does not exist)

I need to use the compiled data using CTE and then convert the columns to rows using crosstab(open to other ideas) in the next select statement. Below is the query.
with checked_adgroup AS (
SELECT
ua.new_adgroup,
ua.account,
ua.campaign,
ua.ad_group,
ua."position",
cp.category,
pt.full_value,
FROM unnest_adgroup ua
LEFT JOIN taxonomy_category cp ON ua."position" = cp."position"
LEFT JOIN taxonomy pt ON ua.short_val = pt.short_value AND cp.category = pt.category AND (pt.lob IS NULL OR pt.lob = ua.lob)
)
SELECT *
from crosstab(
'select
cad.account,
cad.campaign,
cad.ad_group,
cad.category,
cad.full_value
FROM checked_adgroup cad
WHERE cad.all_correct AND cad.category IS NOT NULL
ORDER BY 1,2,3')
AS final_result(
account text, campaign text, ad_group text,
division text, lob text, match_type text );
Error message:
ERROR: relation "checked_adgroup" does not exist LINE 7: FROM checked_adgroup cad
Output of checked_adgroup cte looks like below:
enter image description here
Desired output of the final statement is:
enter image description here
Welcome to the community. First off please do not post images, they are useless to work with, and in some instances they are prohibited and cannot be viewed. Instead use formatted text.
I haven't used crosstab functionality all that much, but it does offer a second version which contains 2 queries, the second feeding into the first. There are however a couple errors in your posted query that would need correcting either way. So that first. Look for --<< tag.
with checked_adgroup AS (
SELECT
ua.new_adgroup,
ua.account,
ua.campaign,
ua.ad_group,
ua."position",
cp.category,
pt.full_value,
--<< missing column or ending , above should not be there, assumption missing column see below.
FROM unnest_adgroup ua
LEFT JOIN taxonomy_category cp ON ua."position" = cp."position"
LEFT JOIN taxonomy pt ON ua.short_val = pt.short_value AND cp.category = pt.category AND (pt.lob IS NULL OR pt.lob = ua.lob)
)
SELECT *
from crosstab(
'select
cad.account,
cad.campaign,
cad.ad_group,
cad.category,
cad.full_value
FROM checked_adgroup cad
WHERE cad.all_correct AND cad.category IS NOT NULL
--<< above line has 2 errors:
--<< Incorrectly formatted needs to cad.all_correct is not null AND cad.category IS NOT NULL
--<< column cad.all_correct does not exist (see missing column above
ORDER BY 1,2,3')
AS final_result(
account text, campaign text, ad_group text,
division text, lob text, match_type text);
Now we need to transform the CTE to a second query that crosstab might be ale to use. I have identified each with Postgres $Quoting$, not so much from necessity as standard string quote (') would be sufficant, but more from visibility standing.
select *
from crosstab(
$ct1$select
account,
campaign,
ad_group,
category,
full_value
--<< from checked_adgroup cad
--<< where cad.all_correct and cad.category is not null
--<< moved above lines to second query to avoid reference and removed qualification
order by 1,2,3
$ct1$
, $ct2$select *
from (
select
ua.new_adgroup,
ua.account,
ua.campaign,
ua.ad_group,
ua."position",
cp.category,
pt.full_value,
'mssing from orig posted query' all_correct
from unnest_adgroup ua
left join taxonomy_category cp on ua."position" = cp."position"
left join taxonomy pt on ua.short_val = pt.short_value
and cp.category = pt.category
and (pt.lob is null or pt.lob = ua.lob)
) s
where all_correct is not null and cad.category is not null
--<< move from query1
$ct2$ )
as final_result(
account text, campaign text, ad_group text,
division text, lob text, match_type text );
But at this point I get an error relationship unnest_adgroup does not exist. Which is true as you did not post the definition, not other referenced tables. But that seems to imply the syntax is correct.
Admittedly, this may be way off base if so, so be it, I can always delete later. But, I stuck at home with no other projects at the moment and this seems like an interesting question. Looking forward to the results. Good Luck.

My SQL query runs well in SQL dev and returns Two records but it returns blank value when I use same query in "Add Command" in Crystal report

I have a SQL query in sql Developer(Oracle Database),which run well and returns 4 columns and 2 records but if I use the same query in Add Command in Crystal report it returns blank values.
p.Name (In DB in schema1, Data type VARCHAR2(100 Char), Eg: "SAP Consulting LLC")
TN.TNA (In DB in schema1, Data type VARCHAR2(25 Char), Eg: "123-456788")
P.SUB (In DB in schema1, Data type VARCHAR2(25 Char), Eg: "0")
P.M_NO (In DB in schema1, Data type VARCHAR2(25 Char), Eg: "123456")
with ABC as (
select pnc.p_id from schema1.pp_pnc pnc, schema1.pp_n pn
where PNC.N_ID = PN.id
and PN.DS = 'ABC'
and PNC.END_DATE like '01-JAN-20'),
EFG as (select pnc.p_id from schema1.pp_pnc pnc, schema1.pp_n pn
where PNC.N_ID = PN.id
and PN.DS = 'EFG'
and PNC.END_DATE like '01-JAN-00')
select distinct P.name, TN.TNA, P.SUB , P.M_NO
from schema.PETA P
inner join SCHEMA1.ALPHA PTPC on P.id = PTPC.P_ID
inner join schema1.BETA TN on PTPC.TN_ID = TN.id
inner join ABC on P.id=ABC.P_ID
inner join EFG on P.id=EFG.P_ID
where PTPC.END_DATE > sysdate
and TN.TNA not in ('123-456788', '456-457896')

Using a UDF multiple times in a Sproc

I have a SQL 2k5 sproc I'm working with.
I need to reference a UDF to calculate price based on a few variables and the users permissions. I originally tried this, but it didn't work because I wasn't referencing a field...
SELECT dbo.f_GetPrice(model,userid,authType) 'YourPrice', name, description
FROM tblRL_Products
WHERE 'YourPrice' Between #fromPrice AND #toPrice
OR 'YourPrice' IS NULL
So I modified this to
SELECT dbo.f_GetPrice(model,userid,authType) 'YourPrice', name, description
FROM tblRL_Products
WHERE dbo.f_GetPrice(model,userid,authType) Between #fromPrice AND #toPrice
OR dbo.f_GetPrice(model,userid,authType) IS NULL
When SQL executes this sproc, is it running the function 3X's for each record or does it run it the one time and use the values in the other two places per row.
Is there a more efficient way of doing this?
Edit
This is the Scalar UDF. It needs to grab a price based on the type the user is authorized for, then once we have the right price we need to do a calculation on it. This is all stored in the authorization tables. Every user has an authorization for each line of products. So they may have different price types and calculations for each line, returning back dozens or even hundreds of lines in a single search result call.
In the above code I used authType, that was an old call, we don't use that parameter anymore.
ALTER function [dbo].[f_GetPrice]
(
#model uniqueidentifier,
#userID uniqueidentifier
)
returns money
as
begin
Declare #yourPrice money
WITH ProductPrice AS(
SELECT (CASE PriceType
WHEN 'msrp' THEN p.price_msrp
WHEN 'jobber' THEN p.price_jobber
WHEN 'warehouse' THEN p.price_warehouse
WHEN 'margin' THEN p.price_margin
WHEN 'mycost' THEN p.price_mycost
WHEN 'customprice1' THEN p.price_custom1
WHEN 'customprice2' THEN p.price_custom2
WHEN 'customprice3' THEN p.price_custom2
ELSE p.price_msrp
END) as YourPrice, aup.calc, aup.amount
FROM products p
JOIN lines l ON l.lineID=l.lineID
JOIN authorizations a ON l.authlineID=a.authlineID
JOIN authorizationusers au ON a.auID=au.auID
JOIN authorizationuserprices aup ON au.aupID=aup.aupID
WHERE au.userID=#userID AND p.modelID=#model)
SELECT #yourPrice=(CASE calc
WHEN 'amount' THEN YourPrice+amount
WHEN 'percent' THEN YourPrice+(YourPrice*amount/100)
WHEN 'divide' THEN YourPrice/amount
WHEN 'factore' THEN YourPrice*amount
WHEN 'none' THEN YourPrice
ELSE YourPrice
END) FROM ProductPrice
return #yourPrice
END
If you must use a udf for this, then use a subquery and filter outside the subquery:
select YourPrice, name, description
from
(
SELECT dbo.f_GetPrice(model,userid,authType) YourPrice, name, description
FROM tblRL_Products
) d
WHERE YourPrice Between #fromPrice AND #toPrice
OR YourPrice IS NULL
Then you are only calling your udf once instead of 3 times.
Scalar functions are not good, when they have to be applied to a quite number of rows. In this case definitely you can convert your scalar function into table-valued function, which will not be called one time for every row of input data.
create function [dbo].[ft_GetPrice]
(
#model uniqueidentifier,
#userID uniqueidentifier
)
returns table
as return
(
WITH ProductPrice AS (
SELECT (CASE PriceType
WHEN 'msrp' THEN p.price_msrp
WHEN 'jobber' THEN p.price_jobber
WHEN 'warehouse' THEN p.price_warehouse
WHEN 'margin' THEN p.price_margin
WHEN 'mycost' THEN p.price_mycost
WHEN 'customprice1' THEN p.price_custom1
WHEN 'customprice2' THEN p.price_custom2
WHEN 'customprice3' THEN p.price_custom2
ELSE p.price_msrp
END) as YourPrice, aup.calc, aup.amount
FROM products p
JOIN lines l ON l.lineID=l.lineID
JOIN authorizations a ON l.authlineID=a.authlineID
JOIN authorizationusers au ON a.auID=au.auID
JOIN authorizationuserprices aup ON au.aupID=aup.aupID
WHERE au.userID=#userID AND p.modelID=#model
)
SELECT
CASE calc
WHEN 'amount' THEN YourPrice+amount
WHEN 'percent' THEN YourPrice+(YourPrice*amount/100)
WHEN 'divide' THEN YourPrice/amount
WHEN 'factore' THEN YourPrice*amount
WHEN 'none' THEN YourPrice
ELSE YourPrice
END as YourPrice
FROM ProductPrice
)
GO
Which can be used then as:
SELECT fp.YourPrice, name, description
FROM tblRL_Products
outer apply dbo.ft_GetPrice(model, userid, authType) fp
WHERE fp.YourPrice Between #fromPrice AND #toPrice OR fp.YourPrice IS NULL

Postgres CTE : type character varying(255)[] in non-recursive term but type character varying[] overall

I am new to SO and postgres so please excuse my ignorance. Attempting to get the cluster for a graph in postgres using a solution similar to the one in this post Find cluster given node in PostgreSQL
the only difference is my id is a UUID and I am using varchar(255) to store this id
when i try to run the query I get the following error (but not sure how to cast):
ERROR: recursive query "search_graph" column 1 has type character varying(255)[] in non-recursive term but type character varying[] overall
SQL state: 42804
Hint: Cast the output of the non-recursive term to the correct type.
Character: 81
my code (basically same as previous post):
WITH RECURSIVE search_graph(path, last_profile1, last_profile2) AS (
SELECT ARRAY[id], id, id
FROM node WHERE id = '408d6b12-d03e-42c2-a2a7-066b3c060a0b'
UNION ALL
SELECT sg.path || m.toid || m.fromid, m.fromid, m.toid
FROM search_graph sg
JOIN rel m
ON (m.fromid = sg.last_profile2 AND NOT sg.path #> ARRAY[m.toid])
OR (m.toid = sg.last_profile1 AND NOT sg.path #> ARRAY[m.fromid])
)
SELECT DISTINCT unnest(path) FROM search_graph;
Try casting the SELECT lists in the recursive and non-recursive terms to varchar.
WITH RECURSIVE search_graph(path, last_profile1, last_profile2) AS (
SELECT ARRAY[id]::varchar[], id::varchar, id::varchar
FROM node WHERE id = '408d6b12-d03e-42c2-a2a7-066b3c060a0b'
UNION ALL
SELECT (sg.path || m.toid || m.fromid)::varchar[], m.fromid::varchar, m.toid::varchar
FROM search_graph sg
JOIN rel m
ON (m.fromid = sg.last_profile2 AND NOT sg.path #> ARRAY[m.toid])
OR (m.toid = sg.last_profile1 AND NOT sg.path #> ARRAY[m.fromid])
)
SELECT DISTINCT unnest(path) FROM search_graph;

Dynamic pivot - how to obtain column titles parametrically?

I wish to write a Query for SAP B1 (t-sql) that will list all Income and Expenses Items by total and month by month.
I have successfully written a Query using PIVOT, but I do not want the column headings to be hardcoded like: Jan-11, Feb-11, Mar-11 ... Dec-11.
Rather I want the column headings to be parametrically generated, so that if I input:
--------------------------------------
Query - Selection Criteria
--------------------------------------
Posting Date greater or equal 01.09.10
Posting Date smaller or equal 31.08.11
[OK] [Cancel]
the Query will generate the following columns:
Sep-10, Oct-10, Nov-10, ..... Aug-11
I guess DYNAMIC PIVOT can do the trick.
So, I modified one SQL obtained from another forum to suit my purpose, but it does not work. The error message I get is Incorrect Syntax near 20100901.
Could anybody help me locate my error?
Note: In SAP B1, '[%1]' is an input variable
Here's my query:
/*Section 1*/
DECLARE #listCol VARCHAR(2000)
DECLARE #query VARCHAR(4000)
-------------------------------------
/*Section 2*/
SELECT #listCol =
STUFF(
( SELECT DISTINCT '],[' + CONVERT(VARCHAR, MONTH(T0.RefDate), 102)
FROM JDT1
FOR XML PATH(''))
, 1, 2, '') + ']'
------------------------------------
/*Section 3*/
SET #query = '
SELECT * FROM
(
SELECT
T0.Account,
T1.GroupMask,
T1.AcctName,
MONTH(T0.RefDate) as [Month],
(T0.Debit - T0.Credit) as [Amount]
FROM dbo.JDT1 T0
JOIN dbo.OACT T1 ON T0.Account = T1.AcctCode
WHERE
T1.GroupMask IN (4,5,6,7) AND
T0.[Refdate] >= '[%1]' AND
T0.[Refdate] <= '[%2]'
) S
PIVOT
(
Sum(Amount)
FOR [Month] IN ('+#listCol+')
) AS pvt
'
--------------------------------------------
/*Section 4*/
EXECUTE (#query)
I don't know SAP, but a couple of things spring to mind:
It looks like you want #listCol to contain a collection of numbers within square brackets, for example [07],[08],[09].... However, your code appears not to put a [ at the start of this string.
Try replacing the lines
T0.[Refdate] >= '[%1]' AND
T0.[Refdate] <= '[%2]'
with
T0.[Refdate] >= ''[%1]'' AND
T0.[Refdate] <= ''[%2]''
(I also added a space before the AND in the first of these two lines while I was editing your question.)