Oracle SQL sum up columns resulted from aggregate function and decode - sql

i have 4 columns resulted from different conditions decode and aggregate function MAX
SELECT MAX(DECODE(pett.element_name,'Basic Salary',peevf.screen_entry_value,0)) Salary,
MAX(DECODE(pett.element_name,'Transportation Allowance',peevf.screen_entry_value,0)) Transportation,
MAX(DECODE(pett.element_name,'Mobile Allowance',peevf.screen_entry_value,0)) Mobile,
MAX(DECODE(pett.element_name,'Housing Allowance',peevf.screen_entry_value,0)) Housing,
i want to make another column that sums up these values as net salary like this:
Salary + Mobile + Housing + Transportation AS "Net Salary"
but it doesn't seem to accept aliases, how can I achieve that? thanks in advance

You can summarize all of them as formulas:
SELECT MAX(DECODE(pett.element_name,'Basic Salary',peevf.screen_entry_value,0)) Salary,
MAX(DECODE(pett.element_name,'Transportation Allowance',peevf.screen_entry_value,0)) Transportation,
MAX(DECODE(pett.element_name,'Mobile Allowance',peevf.screen_entry_value,0)) Mobile,
MAX(DECODE(pett.element_name,'Housing Allowance',peevf.screen_entry_value,0)) Housing,
MAX(DECODE(pett.element_name,'Basic Salary',peevf.screen_entry_value,0))
+
MAX(DECODE(pett.element_name,'Transportation Allowance',peevf.screen_entry_value,0))
+
MAX(DECODE(pett.element_name,'Mobile Allowance',peevf.screen_entry_value,0))
+
MAX(DECODE(pett.element_name,'Housing Allowance',peevf.screen_entry_value,0))
AS "Net Salary"
FROM Table1
OR use a CTE to utilize aliases:
WITH max_table AS
(
SELECT MAX(DECODE(pett.element_name,'Basic Salary',peevf.screen_entry_value,0)) Salary,
MAX(DECODE(pett.element_name,'Transportation Allowance',peevf.screen_entry_value,0)) Transportation,
MAX(DECODE(pett.element_name,'Mobile Allowance',peevf.screen_entry_value,0)) Mobile,
MAX(DECODE(pett.element_name,'Housing Allowance',peevf.screen_entry_value,0)) Housing
FROM Table1
)
SELECT Salary,
Transportation,
Mobile,
Housing,
Salary + Transportation + Mobile + Housing AS "Net Salary"
FROM max_table

If there is only a single row for each element name and you are trying to pivot rows to columns then you can use:
SELECT MAX(
CASE
WHEN pett.element_name = 'Basic Salary'
THEN peevf.screen_entry_value
ELSE 0
END
) AS Salary,
MAX(
CASE
WHEN pett.element_name = 'Transportation Allowance'
THEN peevf.screen_entry_value
ELSE 0
END
) AS Transportation,
MAX(
CASE
WHEN pett.element_name = 'Mobile Allowance'
THEN peevf.screen_entry_value
ELSE 0
END
) AS Mobile,
MAX(
CASE
WHEN pett.element_name = 'Housing Allowance'
THEN peevf.screen_entry_value
ELSE 0
END
) AS Housing,
SUM(
CASE
WHEN pett.element_name IN (
'Basic Salary', 'Transportation Allowance',
'Mobile Allowance', 'Housing Allowance'
)
THEN peevf.screen_entry_value
ELSE 0
END
) AS net_salary,
Or:
SELECT COALESCE(salary, 0) AS salary,
COALESCE(transport, 0) AS transport,
COALESCE(mobile, 0) AS mobile,
COALESCE(housing, 0) AS housing,
COALESCE(salary, 0) + COALESCE(transport, 0)
+ COALESCE(mobile, 0) + COALESCE(housing, 0) AS net_salary
FROM ...
PIVOT (
MAX(peevf.screen_entry_value)
FOR pett.element_name IN (
'Basic Salary' AS salary,
'Transportation Allowance' AS transportation,
'Mobile Allowance' AS mobile,
'Housing Allowance' AS housing
)
)

Related

WITH Clause Syntax error - While using Outer select

I have created a sql which is below, when i am trying to put this under outer select which will l just display the results that are rendered from below WITH clause query it is giving me error in sql server, where as working fine with Oracle.
I don't want to create a view i want to put this below ouptut in merge statement...
select custno, slipno, category, donation, unique_nm from
(
-- Here it is throwing error
with got_debit_custno (custno, slipno, category, donation, debit_custno) as
(
select custno, slipno, category, donation
, case
when category = 'CREDIT'
then 'N/A'
else custno
end
from a
)
, prep (custno, slipno, category, donation, debit_custno, rn, rdt) as
(
select dc.*
, row_number () over (partition by debit_custno, category order by donation, slipno)
, sum (donation) over (partition by debit_custno, category order by donation, slipno)
from got_debit_custno dc
)
, r (custno, slipno, category, donation, debit_custno, rn, rdt, mn) as
(
select custno, slipno, category, donation, debit_custno
, case
when rn = max(rn) over (partition by debit_custno, category)
then rn
end
, rdt, 1
from prep
where rdt <= 27000 or rn = 1
union all
select p.custno, p.slipno, p.category, p.donation, p.debit_custno
, case
when p.rn = max(p.rn) over (partition by p.debit_custno, p.category)
then p.rn
end
, p.rdt, r.mn + 1
from prep p
join r on p.debit_custno = r.debit_custno
and p.category = r.categoRy
and p.rn > r.rn
and (p.rdt <= r.rdt + 27000 or p.rn = r.rn + 1)
)
select custno, slipno, category, donation
, dense_rank () over (order by debit_custno, category, mn) as unique_nm
from r)
order by custno, unique_nm, donation
WITH must be the first keyword of the query. The previous statement must be be terminated by ; as:
;WITH got_debit_custno (custno, slipno, category, donation, debit_custno) as
(
select custno, slipno, category, donation
, case
when category = 'CREDIT'
then 'N/A'
else custno
end
from a
)
, prep (custno, slipno, category, donation, debit_custno, rn, rdt) as
(
select dc.*
, row_number () over (partition by debit_custno, category order by donation, slipno)
, sum (donation) over (partition by debit_custno, category order by donation, slipno)
from got_debit_custno dc
)
, r (custno, slipno, category, donation, debit_custno, rn, rdt, mn) as
(
select custno, slipno, category, donation, debit_custno
, case
when rn = max(rn) over (partition by debit_custno, category)
then rn
end
, rdt, 1
from prep
where rdt <= 27000 or rn = 1
union all
select p.custno, p.slipno, p.category, p.donation, p.debit_custno
, case
when p.rn = max(p.rn) over (partition by p.debit_custno, p.category)
then p.rn
end
, p.rdt, r.mn + 1
from prep p
join r on p.debit_custno = r.debit_custno
and p.category = r.categoRy
and p.rn > r.rn
and (p.rdt <= r.rdt + 27000 or p.rn = r.rn + 1)
)
select custno, slipno, category, donation
, dense_rank () over (order by debit_custno, category, mn) as unique_nm
from r
order by custno, unique_nm, donation

ERROR: syntax error at end of input error when trying to save result of sql query to json

I just run this query
SELECT row_to_json(tt) FROM (
WITH first_admission_time AS
(
SELECT
p.subject_id, p.dob, p.gender
, MIN (a.admittime) AS first_admittime
, MIN( ROUND( (cast(admittime as date) - cast(dob as date)) / 365.242,2) )
AS first_admit_age
FROM patients p
INNER JOIN admissions a
ON p.subject_id = a.subject_id
GROUP BY p.subject_id, p.dob, p.gender
ORDER BY p.subject_id
)
, age as
(
SELECT
subject_id, dob, gender
, first_admittime, first_admit_age
, CASE
-- all ages > 89 in the database were replaced with 300
-- we check using > 100 as a conservative threshold to ensure we capture all these patients
WHEN first_admit_age > 100
then '>89'
WHEN first_admit_age >= 14
THEN 'adult'
WHEN first_admit_age <= 1
THEN 'neonate'
ELSE 'middle'
END AS age_group
FROM first_admission_time
)
select age_group, gender , count(subject_id) as NumberOfPatients from age group by age_group, gender ) tt;
she works fine, and this is the output:
row_to_json
--------------------------------------------------------------
{"age_group":"adult","gender":"F","numberofpatients":15476}
{"age_group":"neonate","gender":"M","numberofpatients":4245}
{"age_group":">89","gender":"F","numberofpatients":1294}
{"age_group":"neonate","gender":"F","numberofpatients":3629}
{"age_group":"adult","gender":"M","numberofpatients":21179}
{"age_group":">89","gender":"M","numberofpatients":697}
(6 rows)
after that I just try to export the result to json format by tapping :
\copy (
SELECT row_to_json(tt) FROM (
WITH first_admission_time AS
(
SELECT
p.subject_id, p.dob, p.gender
, MIN (a.admittime) AS first_admittime
, MIN( ROUND( (cast(admittime as date) - cast(dob as date)) / 365.242,2) )
AS first_admit_age
FROM patients p
INNER JOIN admissions a
ON p.subject_id = a.subject_id
GROUP BY p.subject_id, p.dob, p.gender
ORDER BY p.subject_id
)
, age as
(
SELECT
subject_id, dob, gender
, first_admittime, first_admit_age
, CASE
-- all ages > 89 in the database were replaced with 300
-- we check using > 100 as a conservative threshold to ensure we capture all these patients
WHEN first_admit_age > 100
then '>89'
WHEN first_admit_age >= 14
THEN 'adult'
WHEN first_admit_age <= 1
THEN 'neonate'
ELSE 'middle'
END AS age_group
FROM first_admission_time
)
select age_group, gender , count(subject_id) as NumberOfPatients from age group by age_group, gender ) tt
) TO '/media/mobelite/0e5603b2-b1ad-4662-9869-8d0873b65f80/testJson/PatientAgeAndMortality.json';
I just add copy\ ( .....) TO '/media/mobelite/0e5603b2-b1ad-4662-9869-8d0873b65f80/testJson/PatientAgeAndMortality.json';
this is the error that I found :
ERROR: syntax error at end of input
LINE 1: ...nts from age group by age_group, gender ) test ) TO STDOUT;
The json file is created but empty
PS: I just run this command which also save result in a json file and she works fine :
\copy ( SELECT row_to_json(test) FROM (SELECT gender, COUNT(*) FROM patients GROUP BY gender ) test) TO '/media/mobelite/0e5603b2-b1ad-4662-9869-8d0873b65f80/testJson/test.json';
I don't understand the problem
To fix this error, we must put all the query in a single line.
Thank you #IliaMaskov for the reference Postgres: \copy syntax error in .sql file .

Percentage increase in price based on latest transaction date and previous transaction date

,
I want to get the percentage increase in price by Country and City based on latest transaction date and date of Previous Transaction.
How can I Query this? I am not getting it. This is What I have tried:
SELECT Country,City, Price
From tbl
Group by Country,City
Percentage increase = [( Latest Price - Previous Price ) / Previous Price] * 100
Expected Outout:
Unique Country and City Name + Percentage increase in Price.
Country | City | Percentage
This might be overly complicated.
Set up some random data:
IF OBJECT_ID('tempdb..#Cities') IS NOT NULL
BEGIN
DROP TABLE #Cities;
END;
CREATE TABLE #Cities
(
Country VARCHAR(20)
, City VARCHAR(20)
);
IF OBJECT_ID('tempdb..#Data') IS NOT NULL
BEGIN
DROP TABLE #Data;
END;
CREATE TABLE #Data
(
Country VARCHAR(20)
, City VARCHAR(20)
, Price DECIMAL(13, 4)
, Date DATETIME
);
INSERT INTO #Cities
VALUES ('Country 1', 'City 1'), ('Country 1', 'City 2'), ('Country 1', 'City 3'), ('Country 2', 'City 4'), ('Country 2', 'City 5');
INSERT INTO #Data
SELECT Country
, City
, ROUND(RAND(CHECKSUM(NEWID())) * 100, 4) AS Price
, DATEADD(DAY, ROUND(RAND(CHECKSUM(NEWID())) * 10, 0), GETDATE()) AS Date
FROM #Cities
UNION
SELECT Country
, City
, ROUND(RAND(CHECKSUM(NEWID())) * 100, 4)
, DATEADD(DAY, ROUND(RAND(CHECKSUM(NEWID())) * 10, 0), GETDATE())
FROM #Cities;
--Delete duplicate dates
WITH data3 AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Country,City,Date ORDER BY Country,City,Date) AS RN
FROM #Data
)
DELETE FROM data3 WHERE RN<>1
Query the data to get the most recent price, date and percentage increase:
SELECT Dates.*
, Latest.Price AS Latestprice
, Previous.Price AS Previousprice
, ((Latest.Price - Previous.Price) / Previous.Price) * 100 AS Percentageincrease
FROM
(
SELECT C.*
, Latestdate.Latestdate
, Previousdate.Previousdate
FROM #Cities AS C
LEFT JOIN
(
--Latest Date for each county, city
SELECT Country
, City
, MAX(Date) AS Latestdate
FROM #Data
GROUP BY Country
, City
) AS Latestdate ON Latestdate.Country = C.Country
AND Latestdate.City = C.City
LEFT JOIN
(
--Previous Date for each county, city
SELECT Country
, City
, Date AS Previousdate
FROM
(
SELECT Country
, City
, Date
, RANK() OVER(PARTITION BY Country
, City ORDER BY Date DESC) AS Rank
FROM #Data
) AS A
WHERE Rank = 2
) AS Previousdate ON Previousdate.Country = C.Country
AND Previousdate.City = C.City
) AS Dates
JOIN #Data AS Latest ON Latest.Country = Dates.Country
AND Latest.City = Dates.City
AND Latest.Date = Dates.Latestdate
JOIN #Data AS Previous ON Previous.Country = Dates.Country
AND Previous.City = Dates.City
AND Previous.Date = Dates.Previousdate
And for comparison, using lag() to get the percentage increase for each date. Similar to Gordon's answer:
SELECT D.Country
, D.City
, D.Date
, Lag(Date) OVER(PARTITION BY Country
, City ORDER BY Date) AS Previousdate
, D.Price
, Lag(Price) OVER(PARTITION BY Country
, City ORDER BY Date) AS Previousprice
, 100 * (Price / Lag(Price) OVER(PARTITION BY Country
, City ORDER BY Date) - 1) AS PercentageIncrease
FROM #Data AS D;
Using lag to get the same results (latest info per city) as my first query:
SELECT *
FROM
(
SELECT D.Country
, D.City
, D.Date
, Lag(Date) OVER(PARTITION BY Country
, City ORDER BY Date) AS Previousdate
, D.Price
, Lag(Price) OVER(PARTITION BY Country
, City ORDER BY Date) AS Previousprice
, 100 * (Price / Lag(Price) OVER(PARTITION BY Country
, City ORDER BY Date) - 1) AS Percentageincrease
, ROW_NUMBER() OVER(PARTITION BY Country
, City ORDER BY Date DESC) AS Rn
FROM #Data AS D
) AS A
WHERE Rn = 1
ORDER BY Country
, City;
Use lag():
select t.*,
100 * ((price / lag(price) over (partition by country, city order by t_date) - 1) as increase
from t;

SQL - Help on Converting SQL Syntax to MS Access

I need help on this, I need to convert a SQL syntax to MS Access syntax and I don't know how.
INSERT INTO SampleData2
SELECT
Object_Account, Descriptions, GL_Date, Document_Type,
Document_Number, Company, Subledger, Subledger_Type, ' ',
SUM(Actual_Amount * -1) AS TotalAmount,
(JE_Explantion) AS Explanation
FROM
SampleData
WHERE
CAST(Object_Account AS VARCHAR(20)) + Subledger + JE_Explantion
IN (SELECT CAST(Object_Account AS VARCHAR(20)) + Subledger + JE_Explantion
FROM SampleData
GROUP BY Object_Account, Subledger, JE_Explantion
HAVING COUNT(Object_Account) > 1)
GROUP BY
Object_Account, Descriptions, GL_Date, Document_Type,
Document_Number, Company, Subledger, Subledger_Type, Remarks,
JE_Explantion
MS Access uses & for string concatenation and doesn't support cast(). You might try:
INSERT INTO SampleData2
SELECT Object_Account, Descriptions, GL_Date, Document_Type, Document_Number,
Company, Subledger, Subledger_Type, ' ', Sum(Actual_Amount * -1) AS TotalAmount, (JE_Explantion) As Explanation
FROM SampleData as sd
WHERE EXISTS (SELECT 1
FROM SampleData as sd2
WHERE sd2.Object_Account = sd.Object_Account AND
sd2.Subledger = sd.Subledger AND
sd2.JE_Explantion = sd.JE_Explantion
GROUP BY Object_Account, Subledger, JE_Explantion
HAVING COUNT(Object_Account) > 1
)
GROUP BY Object_Account, Descriptions, GL_Date, Document_Type, Document_Number,
Company, Subledger, Subledger_Type, Remarks, JE_Explantion;

How can I change these into columns?

I've tried using CTE, but haven't been able to figure it out. I want to change the multiple rows into one row with multiple columns going accross. Any way to go about this...
Current Result
ern CostPool
111 NULL
111 5
Desired Result
ern CostPool1 CostPool2
111 NULL 5
SELECT first_name, last_name, ern, pc, title, TitleDesc, OfficeTitle, SUM(earned) earned, fypaydate, q
, [RMTS, Support, or Partial Quarter], SUM(CAST([Staff Employment Status] AS INT)) sumEmpStatus, SUM(CAST(countisMHy AS INT)) sumcountisMHy, SUM(CAST(sumisMHy AS INT)) sumisMHy1
, SUM(CAST(sumEligible AS INT)) sumEligible1
, CostPool
FROM (
SELECT
e.first_name, e.last_name
, fss.ern
, fss.pc
, fss4.title
, u.OfficeTitle
, t.TitleDesc
, SUM(fss.gross*fss.[percent]) earned
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, CASE WHEN cpayfss3 = cpaypdq THEN '1' --full q
WHEN cpayfss3 < cpaypdq THEN '2' --part q
ELSE 'Check'
END [RMTS, Support, or Partial Quarter]
, CASE WHEN COUNT(DISTINCT rc.isMHy) = 2 THEN '9' --split
WHEN fss.pc = 'A' AND COUNT(DISTINCT rc.isMHy) = 1 AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '1' --full
WHEN fss.pc IN ('X', 'O', 'W', 'L', 'K') AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '2' --part
ELSE '0'
END [Staff Employment Status]
, COUNT(DISTINCT rc.isMHy) countisMHy
, SUM(CAST(rc.isMHy AS INT)) sumisMHy
, SUM(CAST(rc.Eligible AS INT)) sumEligible --count distinct too?
, rc.CostPool
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW] fss
LEFT JOIN FIN_DataMart.[dbo].[FSSRC_NEW] rc
ON fss.newrc = rc.RC
AND fss.fypaydate = rc.FY
INNER JOIN
(
SELECT ern, fypaydate, q, COUNT(DISTINCT paydate) cpayfss3
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
GROUP BY fypaydate, q, ern
) fss3
ON fss.ern = fss3.ern
AND fss.fypaydate = fss3.fypaydate
AND fss.q = fss3.q
LEFT JOIN
(
SELECT COUNT(DISTINCT paydate) cpaypdq, fy, q
FROM [FIN_DataMart].[dbo].[FSSPayDateQ]
GROUP BY fy, q
) pdq
ON fss.fypaydate = pdq.fy
AND fss.q = pdq.q
LEFT JOIN
[FIN_DataMart].[dbo].FSSEmployeeInfo e
ON fss.ern = e.ern
INNER JOIN
(
SELECT DISTINCT ern, title, tlvl, fy, q, ROW_NUMBER() OVER (PARTITION BY ern, fy, q ORDER BY title DESC) rn
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
) fss4
ON fss.ern = fss4.ern
AND fss.fypaydate = fss4.fy
AND fss.q = fss4.q
AND fss4.rn = '1'
LEFT JOIN
(
SELECT TCode, TLevel, GenericTDesc as TitleDesc, EED,
ROW_NUMBER() OVER (PARTITION BY TCode, TLevel ORDER BY EED DESC) rn
FROM [FIN_DataMart].[dbo].FSATitle
) t
ON fss4.title = t.TCode
AND case when fss4.tlvl = '' THEN '01' WHEN fss4.tlvl IS NULL THEN '01' ELSE fss4.tlvl END = t.TLevel
AND t.rn = 1
LEFT JOIN FIN_DataMart.[dbo].[FSSUserERN] u
ON fss.ern = u.ern
WHERE fss.fypaydate = 2015
AND fss.q = 1
AND fss.obj <> '049' AND fss.obj NOT LIKE 'x%'
AND fss.title NOT IN ('10209', '1020B', '10234', '10232', '20202', '21205', '30086', '34201')
GROUP BY
fss.ern
, fss.pc
, fss4.title
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, rc.CostPool
, t.TitleDesc
, e.first_name
, e.last_name
, u.OfficeTitle
HAVING SUM(CAST(rc.Eligible AS INT)) >=1
) A
GROUP BY
first_name, last_name, ern, pc, title, fypaydate, q
, [RMTS, Support, or Partial Quarter]
, OfficeTitle
, TitleDesc
, CostPool
ORDER BY first_name, last_name, fypaydate, q
You can look into using the Pivot operator to convert your rows into columns.
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
That method would work, although your sample data and expected result do not quite match the massive query you have posted so I cannot provide a more specific example until you provide more test data/expected outputs (and table schema).