Count who paid group by 1, 2 or 3+ - sql

I have a payment table like the example below and I need a query that gives me how many IDs paid (AMOUNT > 0) 1 time, 2 times, 3 or more times. Example:
+----+--------+
| ID | AMOUNT |
+----+--------+
| 1 | 50 |
| 1 | 0 |
| 2 | 10 |
| 2 | 20 |
| 2 | 15 |
| 2 | 10 |
| 3 | 80 |
+----+--------+
I expect the result:
+-----------+------------+-------------+
| 1 payment | 2 payments | 3+ payments |
+-----------+------------+-------------+
| 2 | 0 | 1 |
+-----------+------------+-------------+
ID 1: Paid 1 time (50). The other payment is 0, so I did not count. So, 1 person paid 1 time.
ID 2: Paid 3 times (10,20,15). So, 1 person paid 3 or more time.
ID 3: Paid 1 time (80). So, 2 persons paid 1 time.
I'm doing manually on excel right now but I'm pretty sure there is a more practical solution. Any ideas?

A little sub-query will do the trick
Declare #YOurTable table (ID int, AMOUNT int)
Insert into #YourTable values
( 1 , 50 ),
( 1 , 0) ,
( 2 , 10) ,
( 2 , 20) ,
( 2 , 15) ,
( 2 , 10) ,
( 3 , 80)
Select [1_Payment] = sum(case when Cnt=1 then 1 else 0 end)
,[2_Payment] = sum(case when Cnt=2 then 1 else 0 end)
,[3_Payment] = sum(case when Cnt>2 then 1 else 0 end)
From (
Select id
,Cnt=count(*)
From #YourTable
Where Amount<>0
Group By ID
) A
Returns
1_Payment 2_Payment 3_Payment
2 0 1

To get the output you want try using a table to form the data and then SELECT from that:
with c as (
select count(*) count from mytable where amount > 0 group by id)
select
sum(case count when 1 then 1 else 0 end) "1 Payment"
, sum(case count when 2 then 1 else 0 end) "2 Payments"
, sum(case when count > 2 then 1 else 0 end) "3 Payments"
from c
Here is an example you can play with to see how the query is working.

Related

Sum (or count) multiple case statement

I have the following table:
Month | Item | Events | Party | Spirit | Faith |
May | 123 | 1 | 1 | 0 | 0 |
June |123 | 1 | 0 | 1 | 1 |
it is basically 1 for yes 0 for no. I need to know how many different categories each item is in each month
I need the following results:
Month | Item | Counts |
May | 123 | 2 |
June| 123 | 3 |
This is NOT working:
select Month, Item,
sum(case when EVENTS = 1 then 1 when PARTY = 1 then 1 when SPIRIT = 1 then 1 when FAITH = 1 then 1 else 0 end) as Counts
from TABLE
group by 1,2
Please help, thanks!
You don't need aggregation:
select Month, Item,
(events + party + spirit + faith) as counts
from t;
CREATE TABLE #T
(
Month varchar(10), Item int, Events bit, Party bit, Spirit bit , Faith bit
)
insert into #T
SELECT 'May' , 123 , 1 , 1 , 0 , 0 union
SELECT 'June' ,123 , 1 , 0 , 1 , 1
select Month, Item, CAST(Events AS INT) + CAST(Party AS INT)+ CAST(Spirit AS
INT) +CAST(Faith AS INT) from #T
Aggregation is not needed. Since the events, party, spirit and faith are bit columns, we need to cast it to int and then add it.

Display equation result

I want to display the results of this equation (B/A+B)*100
I dont want rows of stage=1 and state is open
A are the rows where stage=1 and state is lost
B are the rows where stage=2 or higher irrespective of status
------------------------------------
name |stage| state
------------------------------------
| ABC | 1 | open
| DEF | 1 | open
| ABB | 1 | lost
| ABD | 1 | lost
| PQR | 2 | won
| PQF | 3 | lost
| PQY | 4 | open
| PQN | 5 | won
| PQM | 6 | lost
| PQM | 7 | lost
The result should be (6/6+2)*100= 75 %
SELECT
[equation] = CASE
WHEN (ISNULL([a].[cnt], 0) + ISNULL([b].[cnt], 0)) = 0 THEN NULL
ELSE (ISNULL([b].[cnt], 0) / (ISNULL([a].[cnt], 0) + ISNULL([b].[cnt], 0))) * 100
END
FROM
(
SELECT [cnt] = CAST(0 AS MONEY)
) AS [x]
OUTER APPLY
(
SELECT [cnt] = CAST(COUNT(*) AS MONEY) FROM [my_table] WHERE [stage] = 1 AND [state] = 'lost'
) AS [a]
OUTER APPLY
(
SELECT [cnt] = CAST(COUNT(*) AS MONEY) FROM [my_table] WHERE [stage] > 1
) AS [b];
No need for subqueries or outer apply().
select [B/(A+B)]=
(sum(case when stage >1 then 1.0 else 0.0 end)
/
sum(case
when stage =1 and state = 'lost'
then 1.0
when stage > 1
then 1.0
else null
end))*100
from t
test setup: http://rextester.com/THWUY43139
create table t (name char(3), stage int, state varchar(4))
insert into t values
('ABC',1,'open')
, ('DEF',1,'open')
, ('ABB',1,'lost')
, ('ABD',1,'lost')
, ('PQR',2,'won' )
, ('PQF',3,'lost')
, ('PQY',4,'open')
, ('PQN',5,'won' )
, ('PQM',6,'lost')
, ('PQM',7,'lost');
query:
select
[B]=sum(case when stage >1 then 1 else 0 end)
, [(A+B)]=sum(case
when stage =1 and state = 'lost'
then 1
when stage > 1
then 1
else 0
end)
, [B/(A+B)]=(sum(case when stage >1 then 1.0 else 0.0 end)
/
sum(case
when stage =1 and state = 'lost'
then 1.0
when stage > 1
then 1.0
else null
end))*100
from t
results:
+---+-------+----------+
| B | (A+B) | B/(A+B) |
+---+-------+----------+
| 6 | 8 | 75,00000 |
+---+-------+----------+

how to group column as per its unique value and get count in to different column as per its value?

I am having a Category table as follows,
i want retrieve following results according to scStatusvalue and its count group by catID
catID | 0 | 2 | 3
----- |---|---|---
2 | 1 | 0 | 1
3 | 1 | 1 | 0
4 | 2 | 0 | 1
5 | 0 | 1 | 0
I tried this,select catID,count(scStatus) as [Count] from tableName group by catID,scStatus order by catID but i cant get into column that values.
`
Use a pivot query:
SELECT catID,
SUM(CASE WHEN scStatus = 0 THEN 1 ELSE 0 END) AS [0],
SUM(CASE WHEN scStatus = 2 THEN 1 ELSE 0 END) AS [2],
SUM(CASE WHEN scStatus = 3 THEN 1 ELSE 0 END) AS [3]
FROM Category
GROUP BY catID
pivot operator
select *
from (select catID,scStatusvalue from t) t
pivot (count(scStatusvalue) for scStatusvalue in ([0],[2],[3])) t

How to create sql selection based on condition?

I have the following database which shows characteristics of attributes as follows:
attributeId | attributeCode | groupCode
------------+---------------+-----------
1 | 10 | 50
1 | 10 | 50
1 | 12 | 50
My desired result from a select would be:
attributeId | groupcount | code10 | code12
------------+------------+--------+--------
1 | 1 | 2 | 1
Which means: attributeId = 1 has only one groupCode (50), where attributeCode=10 occurs 2 times and attributeCode=12 occurs 1 time.
Of course the following is not valid, but you get the idea of what I'm trying to achieve:
select attributeId,
count(distinct(groupCode)) as groupcount,
attributeCode = 10 as code10,
attributeCode = 12 as code12
from table
group by attributeId;
Try this:
SELECT attributeId, COUNT(DISTINCT groupCode) AS groupcount,
COUNT(CASE WHEN attributeCode = 10 THEN 1 END) AS code10,
COUNT(CASE WHEN attributeCode = 12 THEN 1 END) AS code12
FROM mytable
GROUP BY attributeId
Demo here

SQL Server Multiple Groupings

I am stumped by what seems like a simple problem.
We have the following Table.
ID--- ---Income--- ---Years Offset--- ---Income By Offset---
1 1000 1 NULL
2 500 1 NULL
3 400 1 NULL
4 0 1 NULL
5 2000 2 NULL
6 0 2 NULL
7 400 2 NULL
What I would love to figure out how to do is to sum all of the income column by the "Years Offset column" and place in the first row of the "Income by Offset column." What would be awesome is if the Income by Offset column has values of 1900 in row 1 and 2400 in row 5 with the rest of them rows being untouched.
I know that this sound like a simple problem. But I have tried Window functions, Row_number(), SELF joining tables and a piece of it is solved with each but am having trouble putting it all together.
Thanks in advance,
George
My Version of Your Table
DECLARE #yourTable TABLE (ID INT,Income INT,[Years Offset] INT,[Income By Offset] INT NULL);
INSERT INTO #yourTable
VALUES (1,1000,1,NULL),
(2,500,1,NULL),
(3,400,1,NULL),
(4,0,1,NULL),
(5,2000,2,NULL),
(6,0,2,NULL),
(7,400,2,NULL);
Actual Query
SELECT ID,
Income,
[Years Offset],
CASE
WHEN ID = MIN(ID) OVER (PARTITION BY [Years Offset])
THEN SUM(Income) OVER (PARTITION BY [Years Offset])
ELSE [Income By Offset]
END AS [Income By Offset]
FROM #yourTable
Results
ID Income Years Offset Income By Offset
----------- ----------- ------------ ----------------
1 1000 1 1900
2 500 1 NULL
3 400 1 NULL
4 0 1 NULL
5 2000 2 2400
6 0 2 NULL
7 400 2 NULL
This should return the required result set:
SELECT ID, Income, [Years Offset],
CASE WHEN ROW_NUMBER() OVER (PARTITION By [Years Offset]
ORDER BY ID) = 1
THEN SUM(Income) OVER (PARTITION BY [Years Offset])
ELSE NULL
END AS [Income By Offset]
FROM mytable
Windowed version of SUM calculates the Income per [Years Offset]. ROW_NUMBER() is used to return this value only for the first row of each [Years Offset] group.
Demo here
How about:
SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE Income
(
ID INT PRIMARY KEY,
Income INT NOT NULL,
YearsOffset Int NOT NULL,
IncomeByOffset INT NULL
)
INSERT INTO Income (ID, Income, YearsOffset)
VALUES (1,1000,1),
(2,500,1),
(3,400,1),
(4,0,1),
(5, 2000, 2),
(6,0,2),
(7,400,2)
Query 1:
UPDATE Income
SET IncomeByOffset = I.IncomeByOffset
From
(
SELECT YearsOffset, SUM(Income) As IncomeByOffset, Min(ID) As MinId
FROM Income
GROUP BY YearsOffset
) I
WHERE Income.YearsOffset = I.YearsOffset
AND Income.Id = I.MinId
Results:
Query 2:
SELECT *
FROM Income;
Results:
| ID | Income | YearsOffset | IncomeByOffset |
|----|--------|-------------|----------------|
| 1 | 1000 | 1 | 1900 |
| 2 | 500 | 1 | (null) |
| 3 | 400 | 1 | (null) |
| 4 | 0 | 1 | (null) |
| 5 | 2000 | 2 | 2400 |
| 6 | 0 | 2 | (null) |
| 7 | 400 | 2 | (null) |