Case statement with grouping - sql

Can you help me write a SELECT statement that returns a single row having columns for each TypeId involved for the transaction number 55?
CREATE TABLE Types
(
Id INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(100) NOT NULL,
CONSTRAINT PK_Types PRIMARY KEY CLUSTERED(Id)
)
GO
INSERT INTO Types
VALUES
('Type1')
,('Type2')
,('Type3')
,('Type4')
,('Type5')
GO
CREATE TABLE Transactions
(
Id INT IDENTITY(1000,1) NOT NULL,
TypeId INT NULL,
TransactionNumber INT NOT NULL,
Amount MONEY NULL,
DateRecorded DATETIME2 NOT NULL,
CONSTRAINT PK_Transactions PRIMARY KEY CLUSTERED(Id),
CONSTRAINT FK_Types FOREIGN KEY(TypeId) REFERENCES Types(Id)
)
GO
INSERT INTO Transactions
VALUES
(1,55,2555.50,SYSDATETIME())
,(3,55,3555.50,SYSDATETIME())
,(4,55,4555.50,SYSDATETIME())
,(5,55,5555.50,SYSDATETIME())
GO
I need a single row returned for each transaction number in the Transactions table.
What I already tried:
SELECT TransactionNumber
,(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
,(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
,(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
,(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
,(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions

SELECT TransactionNumber
,sum(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
,sum(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
,sum(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
,sum(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
,sum(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions group by TransactionNumber;

I think you can do a PIVOT to get required output:
SELECT *
FROM (
SELECT ty.NAME, ISNULL(Amount,0)Amount
FROM TRANSACTIONS t
INNER JOIN Types ty ON ty.Id = t.TypeId
WHERE TransactionNumber = 55
) sub
PIVOT(
SUM(Amount) FOR [Name] IN ([Type1], [Type2], [Type3], [Type4], [Type5])
) AS pivottable
SQL Fiddle

With conditional aggregation:
select Id,
sum(case TypeId when 1 then Amount end) Type1,
sum(case TypeId when 2 then Amount end) Type2,
...
from Transactions
group by Id

I think this would be the query you are looking for:
SELECT
COUNT(CASE WHEN TypeID = 1 THEN 1 ELSE NULL END) '# Transactions Type 1'
, COUNT(CASE WHEN TypeID = 2 THEN 1 ELSE NULL END) '# Transactions Type 2'
, COUNT(CASE WHEN TypeID = 3 THEN 1 ELSE NULL END) '# Transactions Type 3'
, COUNT(CASE WHEN TypeID = 4 THEN 1 ELSE NULL END) '# Transactions Type 4'
, COUNT(CASE WHEN TypeID = 5 THEN 1 ELSE NULL END) '# Transactions Type 5'
FROM TRANSACTIONS
Where TransactionNumber = 55
You can find a working SQLFiddle here.
EDIT:
After you comment I think what you are actually looking for is SUM().
SELECT TransactionNumber
, SUM(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
, SUM(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
, SUM(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
, SUM(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
, SUM(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions
GROUP BY TransactionNumber
SQLFiddle for 2nd query here.

Related

Keep the number of data records but the sum of two other Variables should be calculated

I have a table with Course-Participants, Course_Id and Status.
I want the number of records from Course-Participants to stay the same. But from the combination of Course_Id and Status it should show a total.
It should look like this:
And this is my attempt:
SELECT
[Course_Id]
,Sum(case when Course_ID is not null and Status = 0 THEN 1 else 0 end) as Sum_Status_A
,Sum(case when Course_ID is not null and Status = 1 THEN 1 else 0 end) as Sum_Status_B
,Sum(case when Course_ID is not null and Status = 2 THEN 1 else 0 end) as Sum_Status_C
FROM CourseParticipant
group by course_id
because of the group by statement, I cannot include the course participant in the query. As a result, I cannot output the desired number of data records.
Also select participant_id and add it the the group by:
SELECT
Course_Id,
Participant_id,
Sum(case when Course_ID is not null and Status = 0 THEN 1 else 0 end) as Sum_Status_A,
Sum(case when Course_ID is not null and Status = 1 THEN 1 else 0 end) as Sum_Status_B,
Sum(case when Course_ID is not null and Status = 2 THEN 1 else 0 end) as Sum_Status_C
FROM CourseParticipant
group by course_id, participant_id

Group by several columns with count on another column SQL Server

I'm using SQL SERVER 2012 and I'm struggling with this SQL statement. Basically I have this table
table
I want to group by Date, and Username, with a count on the status column, like below :
query result
How can I achieve this?
You can use an aggredated query with a few conditional SUMs.
SELECT
LastUpdate,
UpdatedBy as User,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) as A
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) as C
SUM(CASE WHEN Status = 'D' THEN 1 ELSE 0 END) as D
SUM(CASE WHEN Status = 'Z' THEN 1 ELSE 0 END) as Z
SUM(CASE WHEN Status = 'X' THEN 1 ELSE 0 END) as X
FROM table
GROUP BY LastUpdate, UpdatedBy
ORDER BY LastUpdate, UpdatedBy
You can try using conditional aggregation
select LastUpdate,UpdatedBy,
count(case when Status='A' then UpdatedBy end) as 'A',
count(case when Status='C' then UpdatedBy end) as 'C',
count(case when Status='D' then UpdatedBy end) as 'D',
count(case when Status='Z' then UpdatedBy end) as 'Z',
count(case when Status='X' then UpdatedBy end) as 'X'
from tablename
group by LastUpdate,UpdatedBy
Ok I figured it out with help from the guys answers
SELECT
CAST(LastUpdate as DATE),
UserName,
SUM(CASE WHEN Status = 1 THEN 1 ELSE 0 END) as [Status_1],
SUM(CASE WHEN Status = 2 THEN 1 ELSE 0 END) as [Status_2],
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END) as [Status_3]
FROM Table
WHERE LastUpdate BETWEEN '2018-11-30 10:013:44.080' AND '2018-12-30 10:013:44.080'
GROUP BY CAST(LastUpdate as DATE), UserName
ORDER BY CAST(LastUpdate as DATE)
This is a sample query where I'm looking for records between two dates. The problem I was having was in part due to filtering on datetime rather than date. The lastupdate column is a datetime so by casting to date it solved the issue

Combining rows with NULL columns

select
COUNT(Table1.ID) as count_shipped,
null as count_shipped
from Table1
where
table1.saleStatus='shipped'
and table1.saleApproved='yes'
union
select
null,
COUNT(Table1.ID) as count_pending
from Table1
where
table1.saleStatus in ('Pending', 'awaiting payment', 'backorder')
This gives this output
count_shipped count_shipped
NULL 5
4 NULL
but I don't want Null I only want 4 5 in one line Can anybody help me how to do this sql server?
You can use a case to sum up your conditions
select sum(case when saleStatus = 'shipped' and table1.saleApproved = 'yes'
then 1
else 0
end) as count_shipped,
sum(case when saleStatus in ('Pending', 'awaiting payment', 'backorder')
then 1
else 0
end) as count_pending
from Table1

DB query: How to count maximum for several columns

Assume I have the following table
claim_date person_type
------------------------
01-01-2012 adult
05-05-2012 adult
12-12-2012 adult
12-12-2012 adult
05-05-2012 child
05-05-2012 child
12-12-2012 child
When I execute the following query:
select
claim_date,
sum(case when person_type = 'adult' then 1 else 0 end) as "nbr_of_adults",
sum(case when person_type = 'child' then 1 else 0 end) as "nbr_of_children"
from my_table
group by claim_date
;
I get this result here:
claim_date nbr_of_adults nbr_of_children
---------------------------------------------
01-01-2012 1 0
05-05-2012 1 2
12-12-2012 2 1
What I would like to receive is the maximum number of adults (here: 2) and the maximum number of children (here: 2).
Is there a way to achieve this with a single query? Thanks for any hints.
Use derived table to get counts, and then select max:
select max(nbr_of_adults) max_adults,
max(nbr_of_children) max_children
from
(
select
sum(case when person_type = 'adult' then 1 else 0 end) as "nbr_of_adults",
sum(case when person_type = 'child' then 1 else 0 end) as "nbr_of_children"
from my_table
group by claim_date
) a
With nested query :
select max(nbr_of_adults) maxAd, max(nbr_of_children), maxCh from
(
select
claim_date,
sum(case when person_type = 'adult' then 1 else 0 end) as "nbr_of_adults",
sum(case when person_type = 'child' then 1 else 0 end) as "nbr_of_children"
from my_table
group by claim_date
)
I don't know what is your dbms, but on sybase it works:
select
max(sum(case when person_type = 'adult' then 1 else 0 end)) as "nbr_of_adults",
max(sum(case when person_type = 'child' then 1 else 0 end)) as "nbr_of_children"
from my_table
group by claim_date
select
person_type,
sum(case when person_type = 'adult' then 1 else 0 end) as "nbr_of_adults",
sum(case when person_type = 'child' then 1 else 0 end) as "nbr_of_children"
from my_table
group by claim_date ;
If your SQL product supports window aggregate functions, you could try something like this:
SELECT DISTINCT
MAX(COUNT(CASE person_type WHEN 'adult' THEN 1 END)) OVER () AS max_adult_count,
MAX(COUNT(CASE person_type WHEN 'child' THEN 1 END)) OVER () AS max_child_count
FROM claim_table
GROUP BY claim_date
I also replaced your conditional SUM with a conditional COUNT, which seemed to me both clearer and more succinct.

question on Group by clause in Sql server

Table: Customer
Name Type Amount
James P 125.00
James P 125.00
James P 125.00
James R 225.00
James R 225.00
Rajiv R 155.00
Rajiv R 155.00
Rajiv R 155.00
Rajiv P 150.00
Rajiv P 150.00
Saran R 175.00
In this table structure I want a output which will give each person’s count of P, count of R, sum of Amount where type = P, Sum of amount where type = R
Any clues for me as stuck up with group by did not help me much in this scenario.
If you want the result as separate records, you simply group on the name and type:
select Name, Type, count(*) as Cnt, sum(Amount) as AmountSum
from Customer
Group by Name, Type
order by Name, Type
Result:
Name Type Cnt AmountSum
James P 3 375.00
James R 2 450.00
Rajiv P 2 300.00
Rajiv R 3 465.00
Saran R 1 175.00
If you want the count and sum for a person in the same record, you have to do some comparisons:
select
Name,
count(case Type when 'P' then 1 else null end) as CntP,
sum(case Type when 'P' then Amount else 0 end) as AmountSumP,
count(case Type when 'R' then 1 else null end) as CntR,
sum(case Type when 'R' then Amount else 0 end) as AmountSumR,
from Customer
Group by Name
order by Name
Result:
Name CntP AmountSumP CntR AmountSumR
James 3 375.00 2 450.00
Rajiv 2 300.00 3 465.00
Saran 0 0.00 1 175.00
One query, no CTE, no derived tables:
SELECT
Name,
SUM(CASE WHEN Type = 'P' THEN 1 ELSE 0 END) AS PCount,
SUM(CASE WHEN Type = 'R' THEN 1 ELSE 0 END) AS RCount,
SUM(CASE WHEN Type = 'P' THEN Amount ELSE 0 END) AS PAmount,
SUM(CASE WHEN Type = 'R' THEN Amount ELSE 0 END) AS RAmount
FROM yourTable
GROUP BY Name
using the
CREATE TABLE customer (name varchar(50), type char(1), amount decimal(6,2));
INSERT INTO customer VALUES ('James', 'P', 125.00);
INSERT INTO customer VALUES ('James', 'P', 125.00);
INSERT INTO customer VALUES ('James', 'P', 125.00);
INSERT INTO customer VALUES ('James', 'R', 225.00);
INSERT INTO customer VALUES ('James', 'R', 225.00);
INSERT INTO customer VALUES ('Rajiv', 'R', 155.00);
INSERT INTO customer VALUES ('Rajiv', 'R', 155.00);
INSERT INTO customer VALUES ('Rajiv', 'R', 155.00);
INSERT INTO customer VALUES ('Rajiv', 'P', 150.00);
INSERT INTO customer VALUES ('Rajiv', 'P', 150.00);
INSERT INTO customer VALUES ('Saran', 'R', 175.00);
SELECT
Name,
SUM(CASE WHEN Type = 'P' THEN 1 ELSE 0 END) AS PCount,
SUM(CASE WHEN Type = 'R' THEN 1 ELSE 0 END) AS RCount,
SUM(CASE WHEN Type = 'P' THEN Amount ELSE 0 END) AS PAmount,
SUM(CASE WHEN Type = 'R' THEN Amount ELSE 0 END) AS RAmount
FROM customer
GROUP BY Name
James 3 2 375.00 450.00
Rajiv 2 3 300.00 465.00
Saran 0 1 0.00 175.00
Edited Answer: After gbn pointed out a mistake in my original answer
SELECT name,
SUM( CASE WHEN [type] = 'P' THEN 1 ELSE 0 END) CountOfP ,
SUM( CASE WHEN [type] = 'R' THEN 1 ELSE 0 END) CountOfR,
SUM( CASE WHEN [type] = 'P' THEN Amount End) SumOfP ,
SUM( CASE WHEN [type] = 'R' THEN Amount END) SumOfR
FROM customer
GROUP BY name
Original Answer
SELECT name,
COUNT( CASE WHEN [type] = 'P' THEN 1 ELSE 0 END) CountOfP ,
COUNT( CASE WHEN [type] = 'R' THEN 1 ELSE 0 END) CountOfR,
SUM( CASE WHEN [type] = 'P' THEN Amount End) SumOfP ,
SUM( CASE WHEN [type] = 'R' THEN Amount END) SumOfR
FROM customer
GROUP BY name