Remove group by field - group-by

I've got an issue while getting data from DB2. I want to summarise the invoice amounts by customer. In one field, (calculated - I've called this InvoicedThisYear) it works out what was invoiced this year and in another it works out what was invoiced in the previous year (calculated, I've called it InvoicedLastYear). However, as it is summariesed I've grouped it by the Cust, but it is also wanting the data grouped by the InvoiceYear, so I've had to include this in the grouping. My problem is in my results I now have zeros for the years where there is no data and duplicates, e.g.:
Cust InvoicedThisYear InvoiceLastYear
abc 0 100
abc 100 0
Ideally I would like to see
Cust InvoicedThisYear InvoicedLastYear
abc 100 100
Here is my code:
SELECT
Cust AS Customer,
(CASE WHEN InvoiceYear = Year(Current Date) THEN sum(InvoiceAmt)ELSE 0 END) as InvoicedThisYear,
(CASE WHEN InvoiceYear = year(Current Date)-1 THEN sum(InvoiceAmt)ELSE 0 END) as InvoicedLastYear
FROM
InvHead
GROUP BY
Cust,
InvoiceYear
HAVING
((CASE WHEN InvoiceYear = Year(Current Date) THEN sum(InvoiceAmt)ELSE 0 END)<>0)
OR
((CASE WHEN InvoiceYear = year(Current Date)-1 THEN sum(InvoiceAmt)ELSE 0 END)<>0)
ORDER BY
Cust
How do I get the desired result? The query will not run if I remove the groupby Invoice Year
As a size note, it works in MS Access without grouping by the Invoice Year!
Thanks,
Michael

You need to put the SUM() around the case statements:
SELECT
Cust AS Customer,
sum(CASE WHEN InvoiceYear = Year(Current Date) THEN InvoiceAmt ELSE 0 END) as InvoicedThisYear,
sum(CASE WHEN InvoiceYear = year(Current Date)-1 THEN InvoiceAmt ELSE 0 END) as InvoicedLastYear
FROM
InvHead
GROUP BY
Cust
ORDER BY
Cust

Related

How to create a pivot table in Postgresql using case when?

I want to create a pivot table using postgresql. I could accomplish this using SQLite, and I thought the logic would be similar, but it doesn't seem to be the case.
Here's the sample table:
create table df(
campaign varchar(50),
date date not null,
revenue integer not null
);
insert into df(campaign,date,revenue) values('A','2019-01-01',10000);
insert into df(campaign,date,revenue) values('B','2019-01-02',7000);
insert into df(campaign,date,revenue) values('A','2018-01-01',5000);
insert into df(campaign,date,revenue) values('B','2018-01-01',3500);
here's my sqlite code to transform the tidy data into pivot table:
select
sum(case when strftime('%Y', date) = '2019' then revenue else 0 end) as '2019',
sum(case when strftime('%Y', date) = '2018' then revenue else 0 end) as '2018',
campaign
from df
group by campaign
the result would be like this:
2018 2019 campaign
5000 10000 A
3500 7000 B
I tried making the similar code using postgres, I will just use the year 2019:
select
sum(case when extract('year' from date) = '2019' then revenue else 0 end) as '2019',
campaign
from df
group by campaign
somehow the code doesn't work, I don't understand what's wrong.
Query Error: error: syntax error at or near "'2019'"
what do I miss here?
db-fiddle link:
https://www.db-fiddle.com/f/f1WjMAAxwSPRvB8BrxECN7/0
The function strftime() is used to extract various parts of a date in SQLite, but is not supported by Postgresql.
Use date_part():
select campaign,
sum(case when date_part('year', date) = '2019' then revenue else 0 end) as "2019",
sum(case when date_part('year', date) = '2018' then revenue else 0 end) as "2018"
from df
group by campaign
Or use Postgresql's FILTER clause:
select campaign,
sum(revenue) filter (where date_part('year', date) = '2019') as "2019",
sum(revenue) filter (where date_part('year', date) = '2018') as "2018"
from df
group by campaign
Also, don't use single quotes for table/column names.
SQLite allows it but Postgresql does not.
It accepts only double quotes which is the SQL standard.
See the demo.

How to fix more than one columns returned error in PostgreSQL

I was trying to write a code to fetch records from a table and group by some columns but the subquery returns "more than one" error.
When I write the codes independently, I get a great awesome result but combining them is a problem.
select
year as Season,
cal_scheme as Scheme,
(case when cal_scheme='Mt.Elgon' then '1000'
when cal_scheme='West Nile' then '2000'
when cal_scheme='Rwenzori' then '1500' else '' end) as Target,
min(today::date) as startdatetime,
max(today::date)-min(today::date) as No_of_days,
(select count(id) as id from
kcl_internal_edit where new_farmer='' or new_farmer is null
group by year, cal_scheme)as growers
from kcl_internal_edit
group by year, cal_scheme
The expected result is to be as follows:
Season Scheme Target Startdatetime No_of_days growers
2019 Mt.Elgon 1000 28-10-2019 5 5
2019 West Nile 2000 29-05-2019 10 1
2018 Mt.Elgon 1500 29-08-2018 207 3
Your query should look like this:
select
year as Season,
cal_scheme as Scheme,
(case when cal_scheme='Mt.Elgon' then '1000'
when cal_scheme='West Nile' then '2000'
when cal_scheme='Rwenzori' then '1500' else '' end) as Target,
min(today::date) as startdatetime,
max(today::date)-min(today::date) as No_of_days,
count(id) FILTER (WHERE new_farmer='' or new_farmer is null) as growers
from kcl_internal_edit
group by year, cal_scheme;
There is no need for a subselect!

Getting the top 2 amount with the most recent dates

My original code was taking all transactions in the last 12 months and compare the top two highest single transaction.
If the highest single gift within that time period is more than two times greater than the 2nd largest single transaction, take the 2nd highest single gift. If the #1 single highest gift is not two times greater, it is used.
I found I need to use the most recent dates with the top 2 amount with the above rules. If I use the last 12 months, I'm not getting all the amount value I need.
How do I change the where statement to get the most recent dates instead of the last 12 months from the current current date.
Input Values
account number, date, and transaction amount.
7428, 01262018, 2
7428, 12302018, 5
16988 02142016, 100
16988 01152016, 25
22450 04191971, 8
22450 08291971, 10
Results
AccountNumber Number Amount
------------------------------
7428 2 5.00
16988 2 25.00
22450 2 10.00
26997 2 10.00
27316 2 25.00
27365 2 25.00
28620 2 10.00
28951 2 10.00
29905 2 5.00
Code:
DECLARE #start_date date
DECLARE #end_date date
SET #start_date = DATEADD(YEAR, -1, GETDATE())
SET #end_date = GETDATE()
SELECT
AccountNumber,
COUNT(amount) as Number,
CASE
WHEN MAX(CASE WHEN row_num = 1 THEN amount END) > MAX(CASE WHEN row_num = 2 THEN amount END) * 2
THEN MAX(CASE WHEN row_num = 2 THEN amount END)
ELSE MAX(CASE WHEN row_num = 1 THEN amount END)
END AS Amount
FROM
(SELECT
*,
ROW_NUMBER() OVER(PARTITION BY AccountNumber ORDER BY amount DESC) AS row_num
FROM
dbo.[T01_TransactionMaster]
WHERE
date >= #start_date AND date < #end_date) AS tt
WHERE
row_num IN (1, 2)
AND amount > 0
-- AND AccountNumber = 301692
GROUP BY
AccountNumber

Using field alias in MSQuery does not work with DB2

This query works in data studio, but fails to show alias in MS Query!
I have tried different types such as "",'',[] and even https://support.microsoft.com/en-us/kb/298955
SELECT 'TRANIN'AS NAME, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150603 AND 20150601 THEN 1 else 0 END) AS CurrentMonth, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150501 AND 20150531 THEN 1 else 0 END) AS LastMonth
FROM ALT3
MS broke MS query a long time ago...
I've tried to get it to work right, but nothing worked. I've pretty much given up.
Normally I just rename the column once the data is back in Excel.
But if you really want the name returned from MS query, this works:
WITH tbl AS (SELECT 'TRANIN'AS NAME
, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150603 AND 20150601
THEN 1 else 0 END) AS CurrentMonth
, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150501 AND 20150531
THEN 1 else 0 END) AS LastMonth
FROM ALT3)
SELECT * FROM TBL

Union Statement that can be changed to Case statement

Good Day Everyone!
well i have this kind of code and it kinda ugly,
a friend of mine told me i can implement Case Statements in here, but i do not know how or how would i implement, the code is long so if you could just help me to optimize my code i would appreciate it greatly!
PS. please be gentle to me, im new in T-sql :)
Thank yoU!
SELECT
SUM(CYJEWELRY) 'CY_Jewelry'
,SUM(CYAPPLICANCE) 'CY_Appliance'
,SUM(CYCELLPHONE) 'CY_Cellphone'
,SUM(PYJEWELRY) 'PY_Jewelry'
,SUM(PYAPPLIANCE) 'PY_Appliance'
,SUM(PYCELLPHONE) 'PY_Cellphone'
FROM
(
---TOTAL NUNG A FORMAT 0,0,0,0,0,0
--------------CURRENT YEAR JEWELRY
SELECT COUNT (*) AS CYJEWELRY,0 AS CYAPPLICANCE,0 AS CYCELLPHONE,0 AS PYJEWELRY,0 AS PYAPPLIANCE,0 AS PYCELLPHONE
FROM #TEMPTABLE1
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------CURRENT YEAR APPLIANCE
SELECT 0,COUNT(*),0,0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 1
UNION
------------CURRENT YEAR CELLPHONE
SELECT 0,0,COUNT(*),0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 2
UNION
---------------LAST YEAR JEWELRY
SELECT 0,0,0,COUNT(*),0,0
FROM #TEMPTABLE2
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------------------LAST YEAR APPLIANCE
SELECT 0,0,0,0,COUNT (*),0
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 1
UNION
-------------------------LAST YEAR CELLPHONE
SELECT 0,0,0,0,0,COUNT(*)
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 2
)A
Assuming your data is bit like this Sql Fiddle Example, try this for the sub query using SUM() and CASE.
SELECT SUM(CASE WHEN fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14 ELSE 0 END) Col1And4,
SUM(CASE WHEN fld_StorageGroupID = 1 THEN 1 ELSE 0 END) Col2And5,
SUM(CASE WHEN fld_StorageGroupID = 2 THEN 1 ELSE 0 END) Col3And6
FROM #TEMPTABLE1
GROUP BY fld_StorageGroupID
Since you are applying the same filter for last 3 columns in the subquery, I have done only first 3 columns here.
EDIT:
I think this is better than above (Note: no need to use SUM() in the main query).
Fiddle Example with data
select col1_4 CY_Jewelry,
col2_5 CY_Appliance,
col3_6 CY_Cellphone,
col1_4 PY_Jewelry,
col2_5 PY_Appliance,
col3_6 PY_Cellphone
from (
select sum(case when id>= 3 and id <= 14 then 1 else 0 end) col1_4,
sum(case when id = 2 then 1 else 0 end) col2_5,
sum(case when id = 3 then 1 else 0 end) col3_6
from t
--group by id
) X