Count of total value and count of individual value - sql

I have a table like:
Id
type
status
1
coach
1.0
2
coach
True
3
client
NULL
4
coach
False
5
client
NULL
6
coach
False
7
client
NULL
8
coach
True
9
coach
1.0
10
client
NULL
I want to:
create a column where coach status is active when value is 1.0 and True else status should be inactive
add count of active and inactive values in another column and and total coach count as another column
Here's the expected output:
Id
type
Status
totalcount
status count
1
coach
Active
6
4
2
coach
Active
6
4
4
coach
Inactive
6
2
6
coach
Inactive
6
2
8
coach
Active
6
4
9
coach
Active
6
4
I tried this code
Select id,
(case when status in (1.0,True)
then 'Active'
else 'Inactive'
end) as Status
from table
Where type ='Coach'
But unable to add count of active and inactive and total coach.

Try the following combination of case expressions coupled with a windowed count:
select id, type,
case when status in ('1.0','True') then 'Active' else 'Inactive' end as Status,
Count(*) over() TotalCount,
Count(*) over(partition by case when status in ('1.0','True') then 1 end) StatusCount
from t
where type='coach'
order by Id;

Related

How to add a condition to count function in PostgreSQL

I have these tables Course, subscription,subscription_Course(A table that creates a relation between Course and subscription), and another with Student. I want to Select all the id_courses that have a subscription count higher than 1 but only want to count the subscriptions from different students. Example: If a Student Subscribes two times the same course I want to have a condition that enables the count function to not count more than one time in these cases
These are my tables:
Student:
idStudent(pk)
cc
nif
1
30348507
232928185
2
30338507
231428185
3
30438507
233528185
4
30323231
3232132
Subscription
idsubscription(pk)
Student(fk)
value_subscription
vouchercurso
date
1
1
100
null
2021-11-01
2
2
150
null
2021-12-11
3
3
160
null
2021-01-03
4
4
500
null
1996-11-07
5
1
900
null
2001-07-05
6
2
432
null
2021-05-09
Subscription_Course
idsubscription(PK/fk)
id_Course(pk/fk)
Grade
1
3
9
2
4
15
3
5
12
6
3
9
5
4
16
2
6
20
6
5
4
For example, when counting within my table Subscription_Course only the id_course:5 would have a count higher than 1 because 3 and 4 have a subscription from the same student.
I have this query for now:
Select id_Course
From Subscription_Course
Group by id_Course
Having Count (id_Course)>1
I don't know what to do to add this condition to the count.
seems like you need to join to Subscription and count unique Student id's:
select id_Course
from Subscription_Course sc
join Subscription s
on s.idsubscription = sc.idsubscription
group by id_Course
having Count(distinct Studentid)>1
You can join the Subscription_Course table with the Subscription table in order to access the id_Student column. Then just count the distinct id_Student values for each id_Course value.
SELECT
Subscription_Course.id_Course,
COUNT(DISTINCT Subscription.id_Student) AS student_count
FROM Subscription_Course
INNER JOIN Subscription
ON Subscription_Course.id_Subscription = Subscription.id_Subscription
GROUP BY Subscription_Course.id_Course
HAVING COUNT(DISTINCT Subscription.id_Student) > 1
ORDER BY student_count DESC;
With result:
id_course | student_count
-----------+---------------
3 | 2
4 | 2
5 | 2

Identify a FK which has the highest value from a list of values in its source table

I have following tables.
Part
id
name
1
Part 1
2
Part 2
3
Part 3
Operation
id
name
part_id
order
1
Op 1
1
10
2
Op 2
1
20
3
Op 3
1
30
4
Op 1
2
10
5
Op 2
2
20
6
Op 1
3
10
Lot
id
part_id
Operation_id
10
1
2
11
2
5
12
3
6
I am selecting the results from Lot table and I want to select a column last_Op which is based on the order value of the operation_id. If value of order for the operation_id is the highest for the respective part_id, return 1 else return 0
SELECT
id,
part_id,
operation_id,
last_Op
FROM Lot
expected result set based on the tables above.
id
part_id
operation_id
last_op
10
1
2
0
11
2
5
1
12
3
6
1
In above example, first row returns last_op = 0 because operation_id = 2 is associated with part_id = 1 and it has the highest order = 30. Since operation_id for this part is not pointing towards the highest order value, 0 is returned.
The other two rows return 1 because operation_id 5 and 6 are associated with part_id 2 and 3 respectively and they are pointing towards the highest 'order' value.
If value of order for the operation_id is the highest for the respective part_id, return 1 else return 0
This sounds like window functions will help:
select l.*,
(case when o.order = o.max_order then 1 else 0 end) as last_op
from lot l left join
(select o.*,
max(o.order) over (partition by o.part_id) as max_order
from operations o
) o
on l.operation_id = o.id;
Note: order is a very poor name for a column because it is a SQL keyword.

Multiply newly entered row with another column value and find Total Sum in SQL

I have 4 tables here, I need to multiply newly entered row value in a table with another row and find the total sum using CustomerId:
CustomerTable:
CustomerId Name EmailId
-------------------------
1 Paul r#r.com
2 John J#j.com
LoyaltyPointTable:
LoyaltyPointsId LoyaltyType Points
---------------------------------------
1 Registration 10
2 Loginstatus 1
3 Downloading 10
4 Redemming 1
5 Sharing 20
6 Refer 10
LoyaltyDetailsTable:
LoyaltyDetailsId LoyaltyPointsId CustomerId Dates
-------------------------------------------------
1 1 1 2015-01-22
2 2 1 2015-01-22
3 3 2 2015-01-22
4 3 1 2015-01-22
5 4 1 2015-01-22
6 4 1 2015-01-24
7 5 1 2015-01-24
This query works fine for the total sum for each LoyaltyType
SELECT
LoayaltyPointsTable.LoyaltyType,
COUNT(CustomerTable.CustomerId) AS UserActions,
SUM(LoayaltyPointsTable.Points) AS TotalPoints
FROM
LoayaltyPointsTable
JOIN
LoyaltyDetailsTable ON LoayaltyPointsTable.LoyaltyPointsId = LoyaltyDetailsTable.LoyaltyPointsId
JOIN
CustomerTable ON CustomerTable.CustomerId = LoyaltyDetailsTable.CustomerId
WHERE
CustomerTable.CustomerId = 1
GROUP BY
LoyaltyDetailsTable.CustomerId ,LoayaltyPointsTable.LoyaltyType
below RedeemPointsTable is created with relation to row redeeming in LoyaltyPointTable:
RedeemPointsTable:
RedeemPointsId CustomerId ShopName BillNo Amount
------------------------------------------------
1 1 Mall x 4757 100
3 1 Mall y SH43 50
4 1 Mall x 7743 10
6 1 Mall x s34a 60
What I am expecting is before calculating the total sum, I want column Amount sum (100+50+10+60) * 1 in Redeeming in LoyaltyPointTable to be added with total points for each CustomerId
Expected output
LoyaltyType UserActions TotalPoints
-------------------------------------
Downloading 1 10
Loginstatus 1 1
Redemming 4 (100+50+10+60)*1(here using Amount in RedeemPointsTable)
Refer 1 10
Registration 1 10
Sharing 1 20
User actions count is 4, it is based on the Amount he entered in RedeemPointsTable
Should I need to make changes in adding a foreign key column in RedeemPointsTable or can you point out my mistake?
Any help would be great.
This is the query which returns desired result:
SELECT
LoyaltyPointTable.LoyaltyType,
CASE
WHEN LoyaltyPointTable.LoyaltyPointsId=4 THEN (SELECT COUNT(amount) FROM RedeemPointsTable where CustomerId=1)
ELSE COUNT(CustomerTable.CustomerId)
END as UserActions,
CASE
WHEN LoyaltyPointTable.LoyaltyPointsId=4 THEN (SELECT SUM(amount) FROM RedeemPointsTable where CustomerId=1)*Points
ELSE SUM(LoyaltyPointTable.Points)
END as TotalPoints
FROM
LoyaltyPointTable
JOIN
LoyaltyDetailsTable ON LoyaltyPointTable.LoyaltyPointsId = LoyaltyDetailsTable.LoyaltyPointsId
JOIN
CustomerTable ON CustomerTable.CustomerId = LoyaltyDetailsTable.CustomerId
WHERE
CustomerTable.CustomerId = 1
GROUP BY
LoyaltyDetailsTable.CustomerId ,LoyaltyPointTable.LoyaltyType
You can check it here

Handle Duplicate Record in Oracle SQL

I have a table with records like below
NAME STATUS xml_configparamdb_id xml_configuration_id
STO INACTIVE 1 1
STO ACTIVE 1 2
BOS ACTIVE 1 3
KYC INACTIVE 1 4
KYC INACTIVE 1 5
ACC ACTIVE 1 6
ACC ACTIVE 1 7
Now result I am interested in is as follows:
NAME STATUS xml_configparamdb_id xml_configuration_id
STO ACTIVE 1 2
BOS ACTIVE 1 3
KYC INACTIVE 1 4
ACC ACTIVE 1 6
That is, I want to select data on basis of STATUS .
Condition -- If STATUS is ACTIVE for both case of same Parameter - select first coming ACTIVE
Condition -- If STATUS is INACTIVE for both case of same Parameter - select first coming INACTIVE
Condition -- If STATUS is ACTIVE & INACTIVE for same Parameter - select ACTIVE
Now I used below query to populate result like above without using PRIMARY KEY Column (xml_configuration_id)
CURSOR cCnfgTypData IS
select distinct name, description, STATUS
from stg_xml_cpdb_configuration
WHERE process_exec_num = 1
AND STATUS = 'ACTIVE'
UNION ALL
select name, description, STATUS
from stg_xml_cpdb_configuration t
where process_exec_num = 1
and STATUS = 'INACTIVE'
and not exists (select * from stg_xml_cpdb_configuration
where name = t.name
and STATUS = 'ACTIVE') order by name, description;
It's showing fine data. But when I execute using PRIMARY KEY Column (xml_configuration_id) like below it's displaying all data without satisfying condition
select distinct name, description, STATUS, xml_configparamdb_id, xml_configuration_id
from stg_xml_cpdb_configuration
WHERE process_exec_num = 1
AND STATUS = 'ACTIVE'
UNION ALL
select name, description, STATUS, xml_configparamdb_id, xml_configuration_id
from stg_xml_cpdb_configuration t
where process_exec_num = 1
and STATUS = 'INACTIVE'
and not exists (select * from stg_xml_cpdb_configuration
where name = t.name
and STATUS = 'ACTIVE') order by name, description;
Use analytic function ROW_NUMBER.
SQL> SELECT name,
2 status,
3 xml_configparamdb_id,
4 xml_configuration_id
5 FROM
6 ( SELECT t.*, row_number() over (partition BY name order by status) rn FROM t
7 )
8 WHERE rn = 1
9 ORDER BY xml_configuration_id
10 /
NAM STATUS XML_CONFIGPARAMDB_ID XML_CONFIGURATION_ID
--- -------- -------------------- --------------------
STO ACTIVE 1 2
BOS ACTIVE 1 3
KYC INACTIVE 1 4
ACC ACTIVE 1 6
SQL>

SQL Query inner joins

I am working on SQL Server 2008 R2.
I have two tables let us say TblGroup and TblComplatedDetails.
TblGroup contains the name of Groups along with MemberId and GroupType (i.e. in Daily, Weekly, Start, End) and TblComplatedDetails contains GroupId (i.e. foreign key of TblGroup) along with completed datetime.
Now I want all the group of specific MemberId except GroupType="End" AND "Start" type of Group only if it has no record in TblCompletedDetails. So the record set is something like below :
TblGroup
==================================
Id MemberId GroupType
==================================
1 1 Daily
2 2 Daily
3 3 Daily
4 1 Weekly
5 1 Start
6 2 Weekly
7 2 Start
8 2 End
9 1 End
10 1 End
TblCompletedDetails
======================================
Id GroupId CompletedDate
======================================
1 1 xxxxxxxxxxxxxx
2 2 xxxxxxxxxxxxxx
3 3 xxxxxxxxxxxxxx
4 4 xxxxxxxxxxxxxx
5 1 xxxxxxxxxxxxxx
6 2 xxxxxxxxxxxxxx
7 3 xxxxxxxxxxxxxx
8 5 xxxxxxxxxxxxxx
9 6 xxxxxxxxxxxxxx
So for MemberId = 1 the desired Groups can be :
=======
GroupId
=======
1
4
But for MemberId = 2 the desired resule is :
=======
GroupId
=======
2
6
7
Because 7 is a "Start" type of Group that has not foreign key in TblCompletedDetails.
Can anyone have idea? Awaiting for your valuable response.
select g.ID GroupID
from TblGroup g
where g.MemberID = #MemberID
and g.GroupType <> 'end'
and
(
-- Row is qualified if it is not start
g.GroupType <> 'start'
-- Or, if it is, does not have an entry in TblCompletedDetails
or not exists (select *
from TblCompletedDetails d
where d.GroupId = g.ID)
)