SQL sum multiple fields with conditions - sql

I'm gonna to make a SUM function with these columns of Profile table when each column is greater than 1.
How can I do it?
bank docs personal
2 1 2

The following counts the rows where the values are greater than 1:
select sum(case when bank > 1 then 1 else 0 end) as bank,
sum(case when docs > 1 then 1 else 0 end) as docs,
sum(case when personal > 1 then 1 else 0 end) as personal
from Profile;
The following counts the number of columns within a row with values greater than 1:
select p.*,
(case when bank > 1 then 1 else 0 end +
case when docs > 1 then 1 else 0 end +
case when personal > 1 then 1 else 0 end
) as cnt
from Profile p;
These are the two most sensible interpretations of our question.

The sum of rows where each column value is greater than one:
select sum(bank + docs + personal)
from Profile
where bank > 1 and docs > 1 and personal > 1
;
with t as (
select 0 as v0, 1 as v1 from dual
union all select 3 as v0, 2 as v1 from dual
)
select sum(v0 + v1)
from t
where v0 > 1 and v1 > 1
;
| SUM(V0+V1) |
| ---------: |
| 5 |
db<>fiddle here

The sum of each individual column when the column is greater than 1: (untested)
select sum(case when isnull(bank,0) > 1 then bank else 0 end) banktotal
,sum(case when isnull(docs,0) > 1 then docs else 0 end) docstotal
,sum(case when isnull(personal,0) > 1 then personal else 0 end) personaltotal
from Profile
isnull() may or may not be needed based on your data and table design.

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

I need to Count the Number of Columns that have value more than 0 in SQL

I want to create a calculated field at the end of the columns where it will count all the Columns having values greater than 0.
Below is a sample Data Set.
Account_number DAY_0 DAY_30 DAY_60 DAY_90 DAY_120
acc_001 99 10 0 0.2 0
You can use case expressions:
select t.*,
( (case when day_0 > 0 then 1 else 0 end) +
(case when day_30 > 0 then 1 else 0 end) +
(case when day_60 > 0 then 1 else 0 end) +
(case when day_90 > 0 then 1 else 0 end) +
(case when day_120 > 0 then 1 else 0 end)
) as num_gt_zero
from t;
That said, you probably constructed this from a group by query. You might be able to put this logic directly into that query. If that is the case, ask a new question, with sample data, desired results, and an appropriate database tag.

One select statement with multiple Group BY on the same column

I have 'TABLE_A' like this:
TVA Amount InvoiceID
----------------------
22 | 10.00 | inv-12
22 |-14.00 | inv-13
25 | 24.00 | inv-14
25 |-36.00 | inv-15
25 |-25.00 | inv-16
25 | 18.50 | inv-17
24 |-16.50 | inv-18
24 | 10.00 | inv-19
The goal is to make a groupBy TABLE_A.TVA value and by SUM(TABLE_A.Amount) > 0 and SUM(TABLE_A.Amount) <0, to get finally the sum of all positive Amounts grouped by TVA value, and the sum of all negative amounts grouped by their TVA value also
my Query is like this:
SELECT TABLE_A.TVA, TABLE_A.InvoiceID,
SUM(TABLE_A.Amount) AS [PositiveTotalAMount],
SUM(TABLE_A.Amount) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA
HAVING SUM(TABLE_A.TVA) > 0
MY question is how to add the second grouping by on negative values, because here i group only on SUM() > 0
You can use a CASE (Transact-SQL) expression:
SELECT
A.TVA,
A.InvoiceID,
SUM(CASE WHEN A.Amount > 0 THEN A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN A.Amount < 0 THEN A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM
TABLE_A A
GROUP BY
A.TVA,
A.InvoiceID
Also, you must include all columns from the select list that are not aggregated to the GROUP BY list. InvoiceID was missing.
I also use the alias A for TABLE_A to increase readability.
With conditional aggregation:
SELECT
TABLE_A.TVA,
SUM(CASE WHEN TABLE_A.Amount > 0 THEN TABLE_A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN TABLE_A.Amount < 0 THEN TABLE_A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA
If you want to include the column TABLE_A.InvoiceID in the grouping then:
SELECT
TABLE_A.TVA,
TABLE_A.InvoiceID,
SUM(CASE WHEN TABLE_A.Amount > 0 THEN TABLE_A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN TABLE_A.Amount < 0 THEN TABLE_A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA, TABLE_A.InvoiceID

Counting the 1's and 2's in a Table

I have this table
SECTION
Which consist of field called
Semester
2
1
1
1
2
1
1
2
2
2
1
2
I need sql to count how many 1's and how many 2's are there
And out put like this
semester 1 | semester 2
6 | 6
Demo here:After testing
select
sum(Case when semester=1 then 1 else 0 end) as 'Semester1',
sum(Case when semester=2 then 1 else 0 end) as 'Semester2'
from section
Try out this:
Select sum(case when semster =1 then 1 else 0 end) as semster1 ,
sum(case when semster =2 then 1 else 0 end) as semster2
from section;
Assuming there are more values than 1 and 2, and that the values are integers:
SELECT semester, count(*)
FROM section
WHERE semester = 1 OR semester = 2
GROUP BY semester

sql subquery that collects from 3 rows

I have a huge database with over 4 million rows that look like that:
Customer ID Shop
1 Asda
1 Sainsbury
1 Tesco
2 TEsco
2 Tesco
I need to count customers that within last 4 weeks had shopped in all 3 shops Tesco Sainsbury and Asda. Can you please advice if its possible to do it with subqueries?
This is an example of a "set-within-sets" subquery. You can solve it with aggregation:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
This structure is quite flexible. So if you wanted Asda and Tesco but not Sainsbury, then you would do:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) = 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
EDIT:
If you want a count, then use this as a subquery and count the results:
select count(*)
from (select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0
) t