Nested Case When with Cast and SUM - sql

I am querying an ODBC through EXCEL and i have managed to get my statement to a certain stage but i am looking to take it a step further. This is because i found that if it is approved it is also considered as pending. So i put together the below statement but it keeps kicking back. Is there a better way i should be nesting this SUM CAST CASE WHEN statement as i will need to repeat this again but instead of doing a count up i will be looking to SUM the revenue which i currently only have in one big bucket.
SELECT
Company_0.CoaCompanyName
, SUM(CASE WHEN CAST( InvoiceCreditItem_0.IciInvoiceApproved as INT) IS 1 THEN 1) AS 'Approved'
ELSE SUM(CASE WHEN InvoiceCreditItem_0.InvoiceCreditID IS NULL THEN 1 ) AS 'Prepared'
ELSE SUM(CASE WHEN InvoiceCreditItem_0.InvoiceCreditID IS NOT NULL THEN 1 END) AS 'Pending'
, InvoiceCreditItem_0.IciCreatedDate
, SUM(InvoiceCreditItem_0.IciTotalNettValue) As 'Total Nett Value'
, SUM(InvoiceCreditItem_0.IciVatValue) AS 'VAT Value'
FROM
SBS.PUB.Company Company_0
, SBS.PUB.InvoiceCreditItem InvoiceCreditItem_0
WHERE
InvoiceCreditItem_0.CompanyID = Company_0.CompanyID
AND (Company_0.CoaCompanyName<>'ATOS')
AND InvoiceCreditItem_0.IciCreatedDate >= ?
GROUP BY
Company_0.CoaCompanyName
, InvoiceCreditItem_0.IciCreatedDate
What i currently see is:
Approved Prepared Pending
1 0 1
1 0 3
0 1 0
1 1 0
What i want to see
Approved Prepared Pending
1 0 0
1 0 2
0 1 0
1 1 0
The next stage i am looking at doing is:
CASE WHEN InvoiceCreditItem_0.InvoiceCreditID IS NULL THEN SUM(InvoiceCreditItem_0.IciTotalNettValue) END) AS 'Prepared Value'
Which i expect to show:
Approved Prepared Pending
0 1000 0

Related

Adding a dummy identifier to data that varies by position and value

I am working on a project in SQL Server with diagnosis codes and a patient can have up to 4 codes but not necessarily more than 1 and a patient cannot repeat a code more than once. However, codes can occur in any order. My goal is to be able to count how many times a Diagnosis code appears in total, as well as how often it appears in a set position.
My data currently resembles the following:
PtKey
Order #
Order Date
Diagnosis1
Diagnosis2
Diagnosis3
Diagnosis 4
345
1527
7/12/20
J44.9
R26.2
NULL
NULL
367
1679
7/12/20
R26.2
H27.2
G47.34
NULL
325
1700
7/12/20
G47.34
NULL
NULL
NULL
327
1710
7/12/20
I26.2
J44.9
G47.34
NULL
I would think the best approach would be to create a dummy column here that would match up the diagnosis by position. For example, Diagnosis 1 with A, and Diagnosis 2 with B, etc.
My current plan is to rollup the diagnosis using an unpivot:
UNPIVOT ( Diag for ColumnALL IN (Diagnosis1, Diagnosis2, Diagnosis3, Diagnosis4)) as unpvt
However, this still doesn’t provide a way to count the diagnoses by position on a sales order.
I want it to look like this:
Diagnosis
Total Count
Diag1 Count
Diag2 Count
Diag3 Count
Diag4 Count
J44.9
2
1
1
0
0
R26.2
1
1
0
0
0
H27.2
1
0
1
0
0
I26.2
1
1
0
0
0
G47.34
3
1
0
2
0
You can unpivot using apply and aggregate:
select v.diagnosis, count(*) as cnt,
sum(case when pos = 1 then 1 else 0 end) as pos_1,
sum(case when pos = 2 then 1 else 0 end) as pos_2,
sum(case when pos = 3 then 1 else 0 end) as pos_3,
sum(case when pos = 4 then 1 else 0 end) as pos_4
from data d cross apply
(values (diagnosis1, 1),
(diagnosis2, 2),
(diagnosis3, 3),
(diagnosis4, 4)
) v(diagnosis, pos)
where diagnosis is not null;
Another way is to use UNPIVOT to transform the columns into groupable entities:
SELECT Diagnosis, [Total Count] = COUNT(*),
[Diag1 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis1' THEN 1 ELSE 0 END),
[Diag2 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis2' THEN 1 ELSE 0 END),
[Diag3 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis3' THEN 1 ELSE 0 END),
[Diag4 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis4' THEN 1 ELSE 0 END)
FROM
(
SELECT * FROM #x UNPIVOT (Diagnosis FOR DiagGroup IN
([Diagnosis1],[Diagnosis2],[Diagnosis3],[Diagnosis4])) up
) AS x GROUP BY Diagnosis;
Example db<>fiddle
You can also manually unpivot via UNION before doing the conditional aggregation:
SELECT Diagnosis, COUNT(*) As Total Count
, SUM(CASE WHEN Position = 1 THEN 1 ELSE 0 END) As [Diag1 Count]
, SUM(CASE WHEN Position = 2 THEN 1 ELSE 0 END) As [Diag2 Count]
, SUM(CASE WHEN Position = 3 THEN 1 ELSE 0 END) As [Diag3 Count]
, SUM(CASE WHEN Position = 4 THEN 1 ELSE 0 END) As [Diag4 Count]
FROM
(
SELECT PtKey, Diagnosis1 As Diagnosis, 1 As Position
FROM [MyTable]
UNION ALL
SELECT PtKey, Diagnosis2 As Diagnosis, 2 As Position
FROM [MyTable]
WHERE Diagnosis2 IS NOT NULL
UNION ALL
SELECT PtKey, Diagnosis3 As Diagnosis, 3 As Position
FROM [MyTable]
WHERE Diagnosis3 IS NOT NULL
UNION ALL
SELECT PtKey, Diagnosis4 As Diagnosis, 4 As Position
FROM [MyTable]
WHERE Diagnosis4 IS NOT NULL
) d
GROUP BY Diagnosis
Borrowing Aaron's fiddle, to avoid needing to rebuild the schema from scratch, and we get this:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d1f7f525e175f0f066dd1749c49cc46d

Counting Values based on certain criteria SQL

I am trying to Write a View for some reporting in our CRM program and I'm having trouble with the counts. We are trying to count the number of referrals based on certain criteria. I feel like the way I wrote the view is incorrect. I am trying to use a CASE statement to make sure it counts the values that I want, but I the numbers I am getting I am not able to validate with reverse engineering.
Did I structure the CASE statement correctly?
(Note: I do realize that client is misspelled, unfortunately whoever wrote the database before I got it had some spelling issues.)
This is what I have written so far:
SELECT Comp_Name, Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Client' Then 1
ELSE NULL END) AS Client_Referrals,
Count(Case WHEN lead_companyprimaryreferralsource IS NOT NULL Then 1 Else Null End) AS Target_Referrals,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Prospect' Then 1 Else Null End) As Prospective_Client_Referral,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Lost_Clent' Then 1 Else Null End) AS Lost_Client_Referral,
Count(Case WHEN mcgr_companyid IS NOT NULL Then 1 Else NULL END) AS Intro_By_MCG
FROM Company
RIGHT JOIN Lead on Lead_PrimaryCompanyID = Comp_CompanyId
RIGHT JOIN MCGRelationships on mcgr_companyid = Comp_CompanyId
WHERE COMP_Name IS NOT NULL
Group By Comp_Name
Here is a Sample of What i'm getting:
Client1 0 0 0 0 1
Client2 0 0 0 0 2
Client3 0 0 0 0 1
Client4 0 0 0 0 1
Client5 0 0 0 0 2
Client6 0 0 0 0 2
Client7 0 0 4 0 4
Client8 0 0 0 0 2
Client9 0 2 2 0 2
Client10 12 6 0 0 12
Client11 0 0 0 0 2
When I just run a query on the table where Client 10 is the Primary Referral source, I get nothing. So I can't account for those 12 instances.
I think your problem may be in the join to MCGRelationships, if each company record can have more than one relationship record. If I'm following you correctly, you want Intro_By_MCG to be 1 if that record exists in MCGRelationships, regardless of the number of times it appears there. By joining the table, your query would be counting a lead once for each MCGRelationship associated with the company the lead comes from. Try this and let us know if the result is different:
SELECT Comp_Name, Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Client' Then 1
ELSE NULL END) AS Client_Referrals,
Count(Case WHEN lead_companyprimaryreferralsource IS NOT NULL Then 1 Else Null End) AS Target_Referrals,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Prospect' Then 1 Else Null End) As Prospective_Client_Referral,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Lost_Clent' Then 1 Else Null End) AS Lost_Client_Referral,
Count(Case WHEN EXISTS (Select Comp_CompanyId FROM MCGRelationships WHERE mcgr_companyid = Comp_CompanyId) Then 1 Else NULL END) AS Intro_By_MCG
FROM Company
RIGHT JOIN Lead on Lead_PrimaryCompanyID = Comp_CompanyId
WHERE COMP_Name IS NOT NULL
Group By Comp_Name

Dynamic SQL Statement Creation - Scala

I have a file with following values
matchId Id
2e0c6c42-68ac-43e0-b130-1b986f61a462 segA
2e0c6c42-68ac-43e0-b130-1b986f61a463 segB
2e0c6c42-68ac-43e0-b130-1b986f61a463 segC
2e0c6c42-68ac-43e0-b130-1b986f61a463 segA
I want pivoted result like below
matchid segA segB segC
2e0c6c42-68ac-43e0-b130-1b986f61a463 1 1 1
2e0c6c42-68ac-43e0-b130-1b986f61a462 1 0 0
This means some id is present in SegA and some in all segments (should be denoted as binary 1's and 0's)
Since number of segments can vary I want SQL statement to be generated dynamically using Scala as below (it should scale up or down as per number of segments e.g. today i have 10 seg tomorrow it can be 5 and so on.)
From SQL (AWS Redshift DB) perspective I can generate below query if I know number of segments already but this can get complicated as number of segment increase.
CREATE TABLE pivotedsegments distkey(match_id) AS (
SELECT match_id,
MAX(CASE WHEN segment='Seg1' then 1 else 0 end) Seg1,
MAX(CASE WHEN segment='Seg2' then 1 else 0 end) Seg2,
MAX(CASE WHEN segment='Seg3' then 1 else 0 end) Seg3,
MAX(CASE WHEN segment='Seg4' then 1 else 0 end) Seg4,
MAX(CASE WHEN segment='Seg5' then 1 else 0 end) Seg5,
MAX(CASE WHEN segment='Seg6' then 1 else 0 end) Seg6,
MAX(CASE WHEN segment='Seg7' then 1 else 0 end) Seg7,
MAX(CASE WHEN segment='Seg8' then 1 else 0 end) Seg8,
MAX(CASE WHEN segment='Seg9' then 1 else 0 end) Seg9,
MAX(CASE WHEN segment='Seg10' then 1 else 0 end) Seg10,
MAX(CASE WHEN segment='Seg11' then 1 else 0 end) Seg11,
.
.
.
.
From some-table group by matchid;
So I want to design an scala API that can read such file and convert result in pivoted manner.
Please suggest.

Multiple conditions in SQL

I have following table:
Employee ID Employee Status Date of Termination
1 A NULL
2 A NULL
3 I 1/1/2016
4 I 12/15/2016
5 I 1/1/2016
I would like to report on the following:
Number of current active employees - 2
Number of inactive employees - 3
Number of employees terminated in last one month - 2
This is the piece of code I used:
select
case when employee_status='A' then count(employee_id) else '' end,
case when employee_status='I' then count(employee_id) else '' end,
case when employee_status='I'
then
(select count(employee_id)
from employee
where date_of_termination between '1/1/2016' and '2/1/2016')
else '' end
from employee
My result set is:
Active | Inactive | Inactive_last_month
2 | 0 | 0
0 | 3 | 2
I would like to achieve the following:
Active | Inactive | Inactive_last_month
2 | 3 | 2
Any recommendations will be appreciated.
You need to SUM up the number of rows that match each criteria:
SELECT
SUM(CASE WHEN date_of_termination IS NULL THEN 1 ELSE 0 END) AS active,
SUM(CASE WHEN date_of_termination IS NOT NULL THEN 1 ELSE 0 END) AS inactive,
SUM(CASE WHEN date_of_termination BETWEEN '20160101' AND '20160201' THEN 1 ELSE 0 END) AS inactive_last_month
FROM
Employee
I've ignored the employee_status column with the assumption that the date is sufficient to determine whether or not the employee is active/inactive - in which case that column probably shouldn't even exist in the table since it's duplicating data.
This should be possible to simplify it using SUM :
select
sum(case when employee_status='A' then 1 else 0 end) as active,
sum(case when employee_status='I' then 1 else 0 end) as inactive,
sum(case when employee_status='I' and date_of_termination between '1/1/2016' and '2/1/2016' then 1 else 0 end) as inactive_last_month
from employee
I woudl wrap the case satements in sum() function and also modify the ELSE part of the CASE Statement to be 0.
so it will look like something like this:
select
SUM(case when employee_status='A' then count(employee_id) else 0 end) AS Active,
SUM(case when employee_status='I' then count(employee_id) else 0 end) AS Inactive,
SUM(case when employee_status='I'
then
(select count(employee_id)
from employee
where date_of_termination between '1/1/2016' and '2/1/2016')
else 0 end) AS Inactive_last_month
from employee

Select Count Where Values greater than 0 SQL Server

I'm trying to figure out how to return a select query showing a count of all values in a column that are greater than 0. Then in the next column show a count of all values that = 0.
Example:
ID ColumnA
1 1
2 2
3 1
4 2
5 0
6 0
7 1
Would return a result for the select query of:
NumberOfGreaterThan0 NumberThatEqual0
5 2
You can use conditional aggregates for this via CASE expression:
SELECT COUNT(CASE WHEN ColumnA > 0 THEN 1 END) AS NumberOfGreaterThan0
,COUNT(CASE WHEN ColumnA = 0 THEN 1 END) AS NumberThatEqual0
FROM YourTable
This works because aggregate functions ignore NULL values.
You can use a couple of count functions over case expressions:
SELECT COUNT(CASE WHEN columa > 0 THEN 1 ELSE NULL END) AS NumberOfGreaterThan0,
COUNT(CASE columa WHEN 0 THEN 1 ELSE NULL END) AS NumberThatEqual0
FROM my_table