Unpivot multiple columns showing incorrect results - sql

My initial query and result looks like below
SELECT * FROM (
SELECT S.CURRENCYCD , S.COMBINEDTXNAMOUNT
, S.INTERCHANGEAMOUNT
, S.OTHERCHARGEAMOUNT
,S.APPLIEDCHARGES
FROM
(SELECT X.CURRENCYCD,
CASE WHEN X.CombinedTxnAmount IS NULL THEN 0 ELSE X.CombinedTxnAmount END AS CombinedTxnAmount,
CASE WHEN X.InterchangeAmount IS NULL THEN 0 ELSE X.InterchangeAmount END AS InterchangeAmount,
CASE WHEN X.OtherChargeAmount IS NULL THEN 0 ELSE X.OtherChargeAmount END AS OtherChargeAmount,
CASE WHEN X.MinimumBillAdjustmentAmount IS NULL THEN 0 ELSE X.MinimumBillAdjustmentAmount END +
CASE WHEN X.AppliedChargeAmount IS NULL THEN 0 ELSE X.AppliedChargeAmount END AS APPLIEDCHARGES FROM
XMLTABLE (XMLNAMESPACES('http://www.eds.com/AgileCard/xsd/ACFMerchantStatement/2013/05' AS "acf",'http://www.eds.com/AgileCard/xsd/ACFMerchant/2012/03' as "acfMerchant")
,'/acf:Statement/acf:ChargeSummaryTotals/acf:ChargeSummaryTotalDetail' passing xmltype ('Myxml')
COLUMNS CURRENCYCD VARCHAR(4) PATH 'acfMerchant:CurrencyCd',
CombinedTxnAmount NUMBER PATH 'acf:CombinedTxnAmount',
InterchangeAmount NUMBER PATH 'acf:InterchangeAmount',
OtherChargeAmount NUMBER PATH 'acf:OtherChargeAmount',
MinimumBillAdjustmentAmount NUMBER PATH 'acf:MinimumBillAdjustmentAmount',
AppliedChargeAmount NUMBER PATH 'acf:AppliedChargeAmount'
)X ) S
The result is:
currencyCD | combinedTxnAmount | InterchangeAmount| OtherChangeAmount|AppliedCharges
GBP | 126.5 | 97.02 | 252.92 | 476.44
I am trying to unpivot this query result but for some reason I am not getting the expected result. Below is my unpivot query.
SELECT * FROM (
SELECT S.CURRENCYCD , S.COMBINEDTXNAMOUNT
, S.INTERCHANGEAMOUNT
, S.OTHERCHARGEAMOUNT
,S.APPLIEDCHARGES
FROM
(SELECT X.CURRENCYCD,
CASE WHEN X.CombinedTxnAmount IS NULL THEN 0 ELSE X.CombinedTxnAmount END AS CombinedTxnAmount,
CASE WHEN X.InterchangeAmount IS NULL THEN 0 ELSE X.InterchangeAmount END AS InterchangeAmount,
CASE WHEN X.OtherChargeAmount IS NULL THEN 0 ELSE X.OtherChargeAmount END AS OtherChargeAmount,
CASE WHEN X.MinimumBillAdjustmentAmount IS NULL THEN 0 ELSE X.MinimumBillAdjustmentAmount END +
CASE WHEN X.AppliedChargeAmount IS NULL THEN 0 ELSE X.AppliedChargeAmount END AS APPLIEDCHARGES FROM
XMLTABLE (XMLNAMESPACES('http://www.eds.com/AgileCard/xsd/ACFMerchantStatement/2013/05' AS "acf",'http://www.eds.com/AgileCard/xsd/ACFMerchant/2012/03' as "acfMerchant")
,'/acf:Statement/acf:ChargeSummaryTotals/acf:ChargeSummaryTotalDetail' passing xmltype ('myxml')
COLUMNS CURRENCYCD VARCHAR(4) PATH 'acfMerchant:CurrencyCd',
CombinedTxnAmount NUMBER PATH 'acf:CombinedTxnAmount',
InterchangeAmount NUMBER PATH 'acf:InterchangeAmount',
OtherChargeAmount NUMBER PATH 'acf:OtherChargeAmount',
MinimumBillAdjustmentAmount NUMBER PATH 'acf:MinimumBillAdjustmentAmount',
AppliedChargeAmount NUMBER PATH 'acf:AppliedChargeAmount'
)X ) S) UNPIVOT ((AMT) FOR TASK IN ((COMBINEDTXNAMOUNT) AS 'Combined Transaction Charge',
(INTERCHANGEAMOUNT) as 'Interchange'
,(OTHERCHARGEAMOUNT) as 'Other Charges'
,(APPLIEDCHARGES) as 'Charges Applied To Account'
))
Below is what this query returns:
currencycd | Task | AMT
GBP | Combined Transaction Charge | 126.5
GBP | Interchange | 0
GBP | Other Charges | 0
GBP | Charges Applied To Account | 0
Only the first unpivot value displays the amount correctly. Remaining values are displayed as zero.
Can someone point me what is going wrong with this query.

Related

IF Else string check condition in sql server

I have a records like below :
Name Count
123456M2.txt NULL
123456M2.txt 15
123456M.txt NULL
First record shoud show me NULL, as there is a number after "M" letter in name and Count < 0
Second record shoud show me 1, and there is a number after "M" letter in name and Count > 0
Third record should show me "some number from another field" as, there is no number after "M" letter in name.
Can you guide me on how to write this query.
I am able to do CASE - WHEN query, but not able to proceed with IF ELSE condition of letter check
CASE
WHEN CHARINDEX('M', [FILE_NAME]) > 0 THEN 'COUNT'
You need to use multiple conditions for each WHEN in the CASE:
(psuedocode)
WHEN {Name contains 'M'} AND {character after 'M' is a number} AND {Count is NULL or < 0} THEN NULL
WHEN {Name contains 'M'} AND {character after 'M' is a number} AND {Count is NULL or < 0} THEN 1
etc...
there is no need to try to add IF..ELSE logic anywhere in your query.
I would phrase this as:
select . . .,
(case when name like '%M[0-9]%' and count > 0 then 1
when name like '%M[0-9]%' then 0
else "some number from another field"
end)
A case expression evaluates the conditions in order, stopping at the first one that evaluates to "true".
Your description is a bit unclear, because NULL is not < 0.
Try the following
DECLARE #TBL TABLE (Name VARCHAR(25), [Count] INT);
INSERT INTO #TBL VALUES
('123456M2.txt', NULL),
('123456M2.txt', 15),
('123456M.txt', NULL);
SELECT *,
CASE WHEN Name LIKE '%M[0-9]%' AND ([Count] IS NULL OR [Count] < 0) THEN --Check for NULL too cause NULL is not < 0
NULL
WHEN Name LIKE '%M[0-9]%' AND [Count] > 0 THEN
1
WHEN Name LIKE '%M.%' THEN
555 --Other value from other column
END AS Results
FROM #TBL;
Results:
+--------------+-------+---------+
| Name | Count | Results |
+--------------+-------+---------+
| 123456M2.txt | | |
| 123456M2.txt | 15 | 1 |
| 123456M.txt | | 555 |
+--------------+-------+---------+

Show 2 count in 1 result

I need to display a single result so that I can extract it.
This is my table named 'TRY'
id | type |
01 | A |
01 | D |
01 | A |
My query is like this:
select
lpad(id,2,'0')||
lpad(count(case when type = 'A' then 1 end),3,'0')||
lpad(count(case when type = 'D' then 1 end),3,'0')||
lpad(count(case when type in ('A','D') then 1 end),3,'0') then 1 end)
as results
from
TRY
group by
id
,type
I want the result to show like this 01002001003 but instead I got 2 result which are like this
01002000002 and 01000001001. I just want to combine the count result as one.
I think that the main thing that you need to consider is how the GROUP BY clause actually works, as you have actually grouped by id and type meaning that you'll never have a positive count for type A and type D on the same row as they are not grouped together.
In your example I have noticed the following and worked to these parameters:
You want to GROUP BY id (not GROUP BY id, type)
Your returned result is a concatenated string which consists of
the id (padded to 2 characters)
the number of Type A's (padded to 3 characters)
the number of type D (padded to 3 characters)
the total number of A's and D's combined. (padded to 3 characters)
You actually also want to be using the SUM function instead of COUNT so something along the lines of the following should work:
Oracle/PLSQL
SELECT
LPAD(id,2,'0')
|| LPAD(SUM(CASE WHEN type = 'A' THEN 1 ELSE 0 END),3,'0')
|| LPAD(SUM(CASE WHEN type = 'A' THEN 1 ELSE 0 END),3,'0')
|| LPAD(SUM(CASE WHEN type = 'A' OR type = 'D' THEN 1 ELSE 0 END),3,'0')
AS results
FROM
TRY
GROUP BY
id
On the unlikely off-chance you're actually using SQL Server or another Database engine the LPAD function will not actually work so using something along the lines of the following may work instead. (Also added in case some non ORACLE users have a similar quandary and it's what I used to resolve your issue)
SELECT
[results] =
RIGHT('00' + CONVERT(VARCHAR,[id]),2)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'A' THEN 1 ELSE 0 END)),3)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'D' THEN 1 ELSE 0 END)),3)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'A' OR type = 'D' THEN 1 ELSE 0 END)),3)
FROM
[TRY]
GROUP BY
[id]

SQL PIVOT Rows Into Matrix With Empty Column Results

I was needing to get my data into a format that works smoothly for kendo grid (example). This example is actually a hack to try to color individual chart bars which isn't available by default. If you format your data correctly you can stack the bars in groups and you are able to color each group.
My data needed to be structured like this with the 1st column names as column headers
names CompletedAllCourses HasExpiredCourses HasNotTakenCourses HasDueCourses
-------------------------------------------------------------------------------------------
CompletedAllCourses 12 NULL NULL NULL
HasDueCourses NULL NULL NULL 4
HasExpiredCourses NULL 8 NULL NULL
HasNotTakenCourses NULL NULL 24 NULL
This is what I had to start with GroupedStats Table
CompletedAllCourses 12
HasDueCourses 4
HasExpiredCourses 8
HasNotTakenCourses 24
I tried the following query from an example I found online.
SELECT * FROM GroupedStats
PIVOT
(
MAX(cnt) FOR cat IN (CompletedAllCourses,
HasExpiredCourses, HasNotTakenCourses, HasDueCourses)
) p
This was the result.
CompletedAllCourses HasExpiredCourses HasNotTakenCourses HasDueCourses
------------------- ----------------- ------------------ -------------
12 8 24 4
I figured out one way and posted it as the answer.
This will give you the required result but it requires hardcoded literals in CASE:
SELECT cat,
CASE cat WHEN 'CompletedAllCourses' THEN CompletedAllCourses ELSE NULL END AS CompletedAllCourses,
CASE cat WHEN 'HasExpiredCourses' THEN HasExpiredCourses ELSE NULL END AS HasExpiredCourses,
CASE cat WHEN 'HasNotTakenCourses' THEN HasNotTakenCourses ELSE NULL END AS HasNotTakenCourses,
CASE cat WHEN 'HasDueCourses' THEN HasDueCourses ELSE NULL END AS HasDueCourses
FROM GroupedStats
JOIN
(
SELECT * FROM GroupedStats
PIVOT
(
MAX(cnt) FOR cat IN (CompletedAllCourses,
HasExpiredCourses, HasNotTakenCourses, HasDueCourses)
) p
) X
ON 1 = 1
SQL Fiddle Demo
PIVOT Example to save the day
I moved this part of this post into the answer because it was ultimately what worked for me.
Need another column to fix things up or things collapse into one result.
select * from
(select cat as names, cnt, cat FROM GroupedStats) x
PIVOT
(
MAX(cnt) FOR cat IN (CompletedAllCourses, HasExpiredCourses,
HasNotTakenCourses, HasDueCourses)
) p
[sql fiddle] (http://sqlfiddle.com/#!6/8b706/3)
And I get the format I wanted PROBLEM SOLVED! Please comment if you can add to the explanation.
names CompletedAllCourses HasExpiredCourses HasNotTakenCourses HasDueCourses
---------------------------------------------------------------------------------------
CompletedAllCourses 12 NULL NULL NULL
HasDueCourses NULL NULL NULL 4
HasExpiredCourses NULL 8 NULL NULL
HasNotTakenCourses NULL NULL 24 NULL

Sql Server 2008: How to order column with null values to show up in the end

I am currently not able to sort the column to show up null values in the end
SELECT firstPart,secondPart FROM Exhibit_table d, ExhibitType a WHERE d.case_id ='13-05'
AND d.ExhibitTypeId = TypeId AND d.ComplianceNo = '0' and active = 1 order by CONVERT(INT, firstPart), secondPart
I have 2 columns firstpart and secondpart I need to sort it such a way that it shows in the following order
10
11
12 A
12 B
12 C
null null
null null
Any help is greatly appreciated
You can add a third sorting condition:
SELECT firstPart,secondPart
FROM Exhibit_table d, ExhibitType a
WHERE d.case_id ='13-05' AND d.ExhibitTypeId = TypeId AND d.ComplianceNo = '0' and active = 1
ORDER BY CASE WHEN firstPart IS NULL AND secondPart IS NULL THEN 0 ELSE 1 END,
CONVERT(INT, firstPart), secondPart
This will introduce a calculated field with value of 0 when both fields are NULL and value of 1 otherwise - and sort by that field. You can adjust that condition as needed.

Alternatives to a self FULL OUTER JOIN to obtaint match between two entries

in my db model I have two entities: Entitlement and Entitlement_Data. Each Entitlement is identified by an incrementing ID (IDENTITY), and can have multiple Entitlement_Data entries, each with a different Type - wich can be either 0 (Weekly) or 1 (Monthly) (EntitlementID and Type are PK for Entitlement_Data, EntitlementID being FK to Entitlement table).
For each Entitlement, I need to:
Get the first non-NULL value from either Monthly (Type=1) or Weekly (Type=0) Entitlement_Data, for a given set of Entitlement_Data attributes (SharesPaid, LocalTaxRate, etc...) - the first part of the SELECT;
Get some indication about match/mismatch between Monthly and Weekly Entitlement_Data entries (SharesPaid_Match, etc...) - the last part of the SELECT.
This is the query I'm using atm:
SELECT
COALESCE(MD.EntitlementID, WD.EntitlementID) AS EntitlementID,
COALESCE(MD.LocalTaxRate, WD.LocalTaxRate) AS LocalTaxRate,
COALESCE(MD.SharesPaid, WD.SharesPaid) AS SharesPaid,
COALESCE(MD.LocalTaxAmount, WD.LocalTaxAmount) AS LocalTaxAmount,
COALESCE(MD.LocalTaxEquivalent, WD.LocalTaxEquivalent) AS LocalTaxEquivalent,
COALESCE(MD.NetReceived, WD.NetReceived) AS NetReceived,
COALESCE(MD.LocalTaxCurrency, WD.LocalTaxCurrency) AS LocalTaxCurrency,
COALESCE(MD.Currency, WD.Currency) AS Currency,
COALESCE(MD.ReleaseDate, WD.ReleaseDate) AS ReleaseDate,
(
CASE
WHEN MD.LocalTaxEquivalent IS NULL OR WD.LocalTaxEquivalent IS NULL THEN NULL
WHEN MD.LocalTaxEquivalent <> WD.LocalTaxEquivalent THEN 0
ELSE 1
END
) AS LocalTaxEquivalent_Match,
(
CASE
WHEN MD.NetReceived IS NULL OR WD.NetReceived IS NULL THEN NULL
WHEN MD.NetReceived <> WD.NetReceived THEN 0
ELSE 1
END
) AS NetReceived_Match,
(
CASE
WHEN MD.SharesPaid IS NULL OR WD.SharesPaid IS NULL THEN NULL
WHEN MD.SharesPaid <> WD.SharesPaid THEN 0
ELSE 1
END
) AS SharesPaid_Match,
(
CASE
WHEN MD.Currency IS NULL OR WD.Currency IS NULL THEN NULL
WHEN MD.Currency <> WD.Currency THEN 0
ELSE 1
END
) AS Currency_Match,
(
CASE
WHEN MD.DividendRate IS NULL OR WD.DividendRate IS NULL THEN NULL
WHEN MD.DividendRate <> WD.DividendRate THEN 0
ELSE 1
END
) AS DividendRate_Match,
(
CASE
WHEN MD.LocalTaxRate IS NULL OR WD.LocalTaxRate IS NULL THEN NULL
WHEN MD.LocalTaxRate <> WD.LocalTaxRate THEN 0
ELSE 1
END
) AS LocalTaxRate_Match
FROM
Entitlement_Data MD
FULL OUTER JOIN Entitlement_Data WD
ON MD.EntitlementID = WD.EntitlementID
WHERE
WD.Type = 0 AND MD.Type = 1
Is there a way to avoid FULL OUTER JOIN and obtain the informations I need? I evaluated the use of a GROUP BY but I don't seem to get the results I need.
Thank you.
Why don't you left join to "main table" which is Entitlement like in following code:
select
COALESCE(MD.EntitlementID, WD.EntitlementID) AS EntitlementID,
COALESCE(MD.LocalTaxRate, WD.LocalTaxRate) AS LocalTaxRate,
COALESCE(MD.SharesPaid, WD.SharesPaid) AS SharesPaid,
COALESCE(MD.LocalTaxAmount, WD.LocalTaxAmount) AS LocalTaxAmount,
COALESCE(MD.LocalTaxEquivalent, WD.LocalTaxEquivalent) AS LocalTaxEquivalent,
COALESCE(MD.NetReceived, WD.NetReceived) AS NetReceived,
COALESCE(MD.LocalTaxCurrency, WD.LocalTaxCurrency) AS LocalTaxCurrency,
COALESCE(MD.Currency, WD.Currency) AS Currency,
COALESCE(MD.ReleaseDate, WD.ReleaseDate) AS ReleaseDate,
(
CASE
WHEN MD.LocalTaxEquivalent IS NULL OR WD.LocalTaxEquivalent IS NULL THEN NULL
WHEN MD.LocalTaxEquivalent <> WD.LocalTaxEquivalent THEN 0
ELSE 1
END
) AS LocalTaxEquivalent_Match,
(
CASE
WHEN MD.NetReceived IS NULL OR WD.NetReceived IS NULL THEN NULL
WHEN MD.NetReceived <> WD.NetReceived THEN 0
ELSE 1
END
) AS NetReceived_Match,
(
CASE
WHEN MD.SharesPaid IS NULL OR WD.SharesPaid IS NULL THEN NULL
WHEN MD.SharesPaid <> WD.SharesPaid THEN 0
ELSE 1
END
) AS SharesPaid_Match,
(
CASE
WHEN MD.Currency IS NULL OR WD.Currency IS NULL THEN NULL
WHEN MD.Currency <> WD.Currency THEN 0
ELSE 1
END
) AS Currency_Match,
(
CASE
WHEN MD.DividendRate IS NULL OR WD.DividendRate IS NULL THEN NULL
WHEN MD.DividendRate <> WD.DividendRate THEN 0
ELSE 1
END
) AS DividendRate_Match,
(
CASE
WHEN MD.LocalTaxRate IS NULL OR WD.LocalTaxRate IS NULL THEN NULL
WHEN MD.LocalTaxRate <> WD.LocalTaxRate THEN 0
ELSE 1
END
) AS LocalTaxRate_Match
from Entitlement e
left join Entitlement_Data wd on e.id = wd.entitlementID and wd.type = 0
left join Entitlement_Data md on e.id = md.entitlementID and md.type = 1
You might limit to rows in Entitlement that have at last one row in Entitlement_Data table (without caring whether is weakly or monthly) using:
where wd.type is not null or md.type is not null