Multiply newly entered row with another column value and find Total Sum in SQL - 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

Related

Oracle SQL find row crossing limit

I have a table which has four columns as below
ID.
SUB_ID. one ID will have multiple SUB_IDs
Revenue
PAY where values of Pay is always less than or equal to Revenue
select * from Table A order by ID , SUB_ID will have data as below
ID SUB_ID REVENUE PAY
100 1 10 8
100 2 12 9
100 3 9 7
100 4 11 11
101 1 6 5
101 2 4 4
101 3 3 2
101 4 8 7
101 5 4 3
101 6 3 3
I have constant LIMIT value 20 . Now I need to find the SUB_ID which Revenue crosses the LIMIT when doing consecutive SUM using SUB_ID(increasing order) for each ID and then find total Pay ##. In this example
for ID 100 Limit is crossed by SUB ID 2 (10+12) . So total Pay
is 17 (8+9)
for ID 101 Limit is crossed by SUB ID 4
(6+4+3+8) . So total Pay is 18 (5+4+2+7)
Basically I need to find the row which crosses the Limit.
Fiddle: http://sqlfiddle.com/#!4/4f12a/4/0
with sub as
(select x.*,
sum(revenue) over(partition by id order by sub_id) as run_rev,
sum(pay) over(partition by id order by sub_id) as run_pay
from tbl x)
select *
from sub s
where s.run_rev = (select min(x.run_rev)
from sub x
where x.id = s.id
and x.run_rev > 20);

How to join two tables - Get a count - As well as show max date

sorry I have no clue on how to do this.
Here is some sample data.
Data Data Entry
Name Active key Name Active Date key
Name 1 1 1 Name 1 1 Jan-15 1
Name 2 0 2 Name 2 1 Feb-15 2
Name 3 1 3 Name 1 1 Jan-14 1
Name 4 1 4 Name 3 1 Feb-15 3
Name 5 1 5 Name 3 0 Jan-14 3
Name 6 0 6 Name 4 1 Feb-15 4
Name 7 1 7 Name 5 1 Mar-15 5
Name 8 1 8 Name 6 1 Apr-15 6
Two tables Data , and Data_Entry you can say.
How do I get an output from this where it shows.
data.active = '1' and data_entry.active = '1' for each key ? as well as the count that it shows up in the data_entry
I would want the output to be for example this : As it is only showing me active data that has an active entry in the data_entry table and the count to be only that of active entries from data_entry
name last_date count
name 1 Jan-15 2
name 3 Feb-15 1
name 4 Feb-15 1
Name 5 Mar-15 1
Name 6 Apr-15 1
I think that should work for you:
SELECT
name,
MAX(date) AS last_date,
COUNT(*) AS count
FROM (
SELECT
data.key
data.name,
data_entry.key,
data_entry.date
FROM data
INNER JOIN data_entry ON data_entry.key = data.key
WHERE data.active = 1 AND data_entry.active = 1
) subquery
GROUP BY key, name

Need hierarichal data from 3 tables in SQL Server

I have following tables:
UserMaster:
UserId Int, UserName Varchar(200),AddedBy Int
UserId EmpName AddedBy
1 admin 0
2 SubAdmin1 1
3 SubAdmin2 1
4 Vikas 2
5 Mohit 4
6 Atul 5
7 Vishal 6
8 Mani 3
9 Sunny 8
SalesMaster:
SalesId Int, UserId Int (FK_UserMaster_UserId) , Price Int
SalesId UserId Price
1 1 100
2 2 200
3 3 300
4 4 500
5 5 100
6 6 200
7 7 111
8 8 222
9 9 333
Case 1: Now I want the price total of all the users who are under the one particular user and its own price also.
Means If i consider UserId=1 , Then the price will be calculated for all users where Column value in AddedBy=1
and their lower level employees.
Means the total Price of users will be calulated for the users having UserId are: 1,2,3,4,5,6,7,8,9.
Case 2: Similarly, If i want to calculate the total price under UserId=3(SubAdmin2) then the total price from the salesMaster will be calculated for the Users having UserId are: 3,8,9
The Result of first Case should be:
UserId Price
1 2066
The Result of Second Case should be:
UserId Price
3 300+222+333
Please Help
Thanks & Regards
Nitin
with cte as (
select #UserId as UserId
union all
select um.UserId
from UserMaster as um
inner join cte as c on c.UserId = um.AddedBy
)
select sum(s.Price)
from cte as c
inner join SalesMaster as s on s.UserId = c.UserId
sql fiddle demo

Calculate aggregated sum from two tables

From the following tables I need to determine which city receives the most pollution from buses.
routes:
route_id | departure_city | destination_city | bus_type | times_per_day
1 2 1 1 4
2 1 3 2 2
3 3 1 2 1
4 1 2 1 5
5 1 3 1 3
bustypes:
bus_type_id | pollution_output
1 3
2 7
For example city 2 is exposed to bus_type 1 four times a day (route_id 1) and bus_type 1 five times a day (route_id 4) giving a pollution output of 27 per day. But I basically need to calculate this for all the cities and return the one with maximum pollution, how do I do that?
SELECT city, sum(pollution) AS total_pollution
FROM (
SELECT r.depature_city AS city
,b.pollution_output * r.times_per_day AS pollution
FROM routes r
JOIN bustypes b ON b.bus_type_id = r.bus_type
UNION ALL
SELECT r.destination_city
,b.pollution_output * r.times_per_day
FROM routes r
JOIN bustypes b ON b.bus_type_id = r.bus_type
) AS sub
GROUP BY city

TSQL - divide rows into groups based on one field

This is modified version of my earlier question: TSQL equally divide resultset to groups and update them
I have my database with 2 tables like so:
Orders table has data like below:
OrderID OperatorID GroupID OrderDesc Status Cash ...
--------------------------------------------------------------------------
1 1 1 small_order 1 300
2 1 1 another_order 1 0
3 1 2 xxxxxxxxxxx 2 1000
5 2 2 yyyyyyyyyyy 2 150
9 5 1 xxxxxxxxxxx 1 50
10 NULL 2 xxxxxxxxxxx 1 150
11 NULL 3 xxxxxxxxxxx 1 -50
12 4 1 xxxxxxxxxxx 1 200
Operators table:
OperatorID Name GroupID Active
---------------------------------------
1 John 1 1
2 Kate 1 1
4 Jack 2 1
5 Will 1 0
6 Sam 3 0
I'm able to equally divide my recordset into equally groups using below query:
SELECT o.*, op.operatorName AS NewOperator, op.operatorID AS NewOperatorId
FROM (SELECT o.*, (ROW_NUMBER() over (ORDER BY newid()) % numoperators) + 1 AS randseqnum
FROM Orders o CROSS JOIN
(SELECT COUNT(*) AS numoperators FROM operators WHERE operators.active=1) op
WHERE o.status in (1,3)
) o JOIN
(SELECT op.*, ROW_NUMBER() over (ORDER BY newid()) AS seqnum
FROM Operators op WHERE op.active=1
) op
ON o.randseqnum = op.seqnum ORDER BY o.orderID
Demo available at: http://sqlfiddle.com/#!3/ff47b/1
Using script from above I can divide Orders to (almost) equal groups but based on number or Orders for Operator, but I need to modify it so that it will assign Operators to Orders based on sum or Cash for orders.
For example:
If I have 6 Orders with Cash values: 300, 0, 50, 150, -50, 200 they sum gives 650.
My script should assign to 3 Operators random 2 Orders with random sum of Cash for Orders.
What I would like to get is to assign for example 300,-50 to operator1, 200, 0 to second and 150, 50 to third.
Hope this sound clear :)
Here is example output that I expect to get:
ORDERID OPERATORID GROUPID DESCRIPTION STATUS CASH NEWOPERATORID
------------------------------------------------------------------------
1 1 1 small_order 1 300 2
2 1 1 another_order 1 0 1
9 5 1 xxxxxxxxxxx 1 50 4
10 (null) 2 xxxxxxxxxxx 1 150 4
11 (null) 3 xxxxxxxxxxx 1 -50 2
12 4 1 xxxxxxxxxxx 1 200 1
How can I (if I can at all) assign Operators to my Orders so that sum or Cash will be closest to average
If I'm understanding this right, could you get the result you want by ordering the Cash column by the biggest, then the smallest, then the next biggest, then the next smallest, etc. Like this:
ROW_NUMBER() over (order by CASE WHEN CashOrder % 2 = 1 then Cash else -Cash END) as splitCash
where you've provided CashOrder lower in the query with
ROW_NUMBER() over (ORDER by CASH) as CashOrder
Then you specify each of your operators depending on this split value, ie (for three operators):
splitCash%3 +1