rolling up data and getting SUM group by - sql

I have two tables:
**OrgPhysicianMappingtbl**
org varchar
physician varchar
**PhysicianDatatbl**
physician varchar
names varchar
datapoint int
data from OrgPhysicianMappingtbl:
+---------+-----------+
| org | physician |
+---------+-----------+
| ABC123 | B032 |
| ABC123 | B023 |
| ABC123 | A022 |
| ABB443 | A32 |
| ABB332 | F23 |
| BVD222 | G23 |
| BVD222 | GG2 |
| BOS5223 | G4 |
+---------+-----------+
data from PhysicianDatatbl:
+------------+----------------------------------+-----------+
| physician | names | datapoint |
+------------+----------------------------------+-----------+
| B032 | CASH | 68 |
| B032 | MEDICAID | 89 |
| B032 | ALL THIRD PARTY | 3,769 |
| B032 | WORKERS COMP | 39 |
| B032 | US SCRIPT (PROC-UNSP) | 86 |
| B032 | MEDCO HLTH SOLUTIONS (PROC-UNSP) | 79 |
| B032 | BCBS WELLPOINT/ANTHEM/WEL UNSPEC | 76 |
| B032 | KY EMPLOYEES HLTH PLN/KEHP (KY) | 62 |
| B032 | UHC/PAC/AARP MED PDP GENERAL(KY) | 52 |
| B032 | WELLCARE OF KENTUCKY (KY) | 42 |
| B032 | CCRX MED PDP GENERAL (KY) | 39 |
| B032 | WORKERS COMP - EMPLOYER | 37 |
| B032 | HUMANA/CAREPLS MED D GENERAL(KY) | 27 |
| B032 | CIGNA MEDICARE RX PDP GNRL (KY) | 26 |
| B023 | CASH | 167 |
| B023 | MEDICAID | 34 |
| B023 | ALL THIRD PARTY | 3,165 |
| B023 | WORKERS COMP | 56 |
| B023 | WORKERS COMP - EMPLOYER | 50 |
| B023 | BLUE CHOICE PPO (TX) | 48 |
| B023 | TRICARE HUMANA MILITARY SOUTH | 47 |
| B023 | MEDCO HLTH SOLUTIONS (PROC-UNSP) | 32 |
| B023 | BROADSPIRE INC | 27 |
| B023 | ADVANCEPCS (PROC-UNSP) | 27 |
| B023 | UNITED HLTHCARE-(TX) TEXAS | 23 |
| B023 | HEALTHSPRING PDP (TX) | 18 |
| B023 | AETNA INC.-(TX) HOUSTON | 13 |
| B023 | WELLCARE MEDICARE D GENERAL(TX) | 12 |
+------------+----------------------------------+-----------+
example of desired result:
+-----------+-----------------+-----------+
| org | names | sum(datapoints|
+-----------+-----------------+-----------+
| ABC123 | CASH | 236 |
| ABC123 | MEDICAID | 123 |
| ABC123 | ALL THIRD PARTY | 6,933 |
| ABC123 | WORKERS COMP | 94 |
| … | … | … |
+-----------+-----------------+-----------+
I need to roll up my data to the ORG level. There are multiple physicians per ORG. every physician has names and datapoints associated with it. The result that I want is the sum of all datapoints per names rolled up to the org level.
Can someone please get me started on this?
here's what i tried:
select o.org,p.names,sum(p.datapoint)
from OrgPhysicianMappingtbl o
join PhysicianDatatbl p
on o.physician=p.physician
group by o.org,p.names

You can use GROUPING SETS:
select o.org, p.names, sum(p.datapoint)
from OrgPhysicianMappingtbl o
inner join PhysicianDatatbl p
on o.physician = p.physician
GROUP BY GROUPING SETS((o.org), (p.names))
see SQL Fiddle with Demo

Well!
SELECT o.org, p.names, sum(p.datapoint)
FROM OrgPhysicianMappingtbl o INNER JOIN PhysicianDatatbl p
ON o.physician = p.physician
GROUP BY o.org, p.names
http://www.sqlfiddle.com/#!2/f59c4/1

select o.org,p.names,sum(p.datapoint)
from OrgPhysicianMappingtbl o
join PhysicianDatatbl p
on o.physician=p.physician
group by o.org,p.names with ROLLUP

Even this should work
SELECT org,names,TotalDP
FROM(
SELECT
o.org
,p.names
,TotalDP = SUM(p.datapoint) OVER(PARTITION BY o.org,p.names)
,Rn = ROW_NUMBER() OVER(PARTITION BY o.org,p.names ORDER BY (SELECT 1))
FROM OrgPhysicianMappingtbl o
JOIN PhysicianDatatbl p on o.physician=p.physician)X WHERE X.Rn = 1

Related

I am trying to connect product sale records to the appropriate purchase record in SQL

I have a transaction table with both purchases and sales. Purchase datetime, quantity, unit cost as well as the corresponding Sales data.
I can separate the transactions with queries no problem there. What I need to do is determine which purchase order supplied the product sold and the difference in purchase and sale rate.
transDate | transType | Product | transQty | transRate
12/5/20 | purchase | pencils | 124 | $5.12
12/6/20 | sale | pencils | 32 | $6.12
12/7/20 | sale | pencils | 67 | $6.21
12/8/20 | purchase | pencils | 65 | $4.85
12/10/20 | sale | pencils | 44 | $6.32
12/11/20 | purchase | pencils | 14 | $6.11
The purchase on 12/5 covers the sales on 12/6, 12/7, and a portion of the sale in 12/10 with the purchase on 12/8 covering the remainder of 12/10.
Reorganized tables
tblPurchaseRecords
pID | transDate | Product | pQty | pTransRate | pRemaining
1 | 12/5/20 | pencils | 124 | $5.12 | 124
2 | 12/8/20 | pencils | 65 | $4.85 | 65
3 | 12/11/20 | pencils | 14 | $6.11 | 14
tblSaleRecords
sID | transDate | Product | sQty | sTransRate | sRemaining
1 | 12/6/20 | pencils | 32 | $6.12 | 32
2 | 12/7/20 | pencils | 67 | $6.21 | 67
3 | 12/10/20 | pencils | 44 | $6.32 | 44
New table
tblProfitLoss
pID | sID | plQty | plRate | plValue
tblProfitLoss is a many-to-many table with sID and pID forming the primary key.
plQty is the MIN(pRemaining, sRemaining). This value is subtracted from both pRemaining and sRemaining. One or both of the two values will be reduced to 0, advancing the respective index(es) by 1.
Resulting in this:
tblPurchaseRecords
pID | transDate | Product | pQty | pTransRate | pRemaining
1 | 12/5/20 | pencils | 124 | $5.12 | 0
+pID | sID | plQty | plRate | plValue
1 | 1 | 32 | $1.00 | $32.00
1 | 2 | 67 | $1.09 | $73.03
1 | 3 | 25 | $1.20 | $30
2 | 12/8/20 | pencils | 65 | $4.85 | 46
+pID | sID | plQty | plRate | plValue
2 | 3 | 19 | $1.47 | $27.93
3 | 12/11/20 | pencils | 14 | $6.11 | 14
tblSaleRecords
sID | transDate | Product | sQty | sTransRate | sRemaining
1 | 12/6/20 | pencils | 32 | $6.12 | 0
+pID | sID | plQty | plRate | plValue
1 | 1 | 32 | $1.00 | $32.00
2 | 12/7/20 | pencils | 67 | $6.21 | 0
+pID | sID | plQty | plRate | plValue
1 | 2 | 67 | $1.09 | $73.03
3 | 12/10/20 | pencils | 44 | $6.32 | 0
+pID | sID | plQty | plRate | plValue
1 | 3 | 25 | $1.20 | $30
2 | 3 | 19 | $1.47 | $27.93
I can do this with VBA but I was hoping to learn how to do it with SQL.

PostgreSQL: Count number of rows in table 1 for distinct rows in table 2

I am working with really big data that at the moment I become confused, looking like I'm just repeating one thing.
I want to count the number of trips per user from two tables, trips and session.
psql=> SELECT * FROM trips limit 10;
trip_id | session_ids | daily_user_id | seconds_start | seconds_end
---------+-----------------+---------------+---------------+-------------
400543 | {172079} | 17118 | 1575550944 | 1575551181
400542 | {172078} | 17118 | 1575541533 | 1575542171
400540 | {172077} | 17118 | 1575539001 | 1575539340
400538 | {172076} | 17117 | 1575540499 | 1575541999
400534 | {172074,172075} | 17117 | 1575537161 | 1575539711
400530 | {172073} | 17116 | 1575447043 | 1575447682
400529 | {172071} | 17115 | 1575496394 | 1575497803
400527 | {172070} | 17113 | 1575495241 | 1575496034
400525 | {172068} | 17115 | 1575485658 | 1575489378
400524 | {172067} | 17113 | 1575488721 | 1575490491
(10 rows)
psql=> SELECT * FROM session limit 10;
session_id | user_id | key | start_time | daily_user_id
------------+---------+--------------------------+------------+---------------
172079 | 43 | hLB8S7aSfp4gAFp7TykwYQ==+| 1575550921 | 17118
| | | |
172078 | 43 | YATMrL/AQ7Nu5q2dQTMT1A==+| 1575541530 | 17118
| | | |
172077 | 43 | fOLX4tqvsyFOP3DCyBZf1A==+| 1575538997 | 17118
| | | |
172076 | 7 | 88hwGj4Mqa58juy0PG/R4A==+| 1575540515 | 17117
| | | |
172075 | 7 | 1O+8X49+YbtmoEa9BlY5OQ==+| 1575538384 | 17117
| | | |
172074 | 7 | XOR7hsFCNk+soM75ZhDJyA==+| 1575537405 | 17117
| | | |
172073 | 42 | rAQWwYgqg3UMTpsBYSpIpA==+| 1575447109 | 17116
| | | |
172072 | 276 | 0xOsxRRN3Sq20VsXWjlrzQ==+| 1575511120 | 17114
| | | |
172071 | 7 | P4beN3W/ZrD+TCpZGYh23g==+| 1575496642 | 17115
| | | |
172070 | 43 | OFi30Zv9e5gmLZS5Vb+I7Q==+| 1575495238 | 17113
| | | |
(10 rows)
Goal: get the distribution of trips per user
Attempt:
psql=> SELECT COUNT(distinct trip_id) as trips
, count(distinct user_id) as users
, extract(year from to_timestamp(seconds_start)) as year_date
, extract(month from to_timestamp(seconds_start)) as month_date
FROM trips
INNER JOIN session
ON session_id = ANY(session_ids)
GROUP BY year_date, month_date
ORDER BY year_date, month_date;
+-------+-------+-----------+------------+
| trips | users | year_date | month_date |
+-------+-------+-----------+------------+
| 371 | 44 | 2016 | 3 |
| 12207 | 185 | 2016 | 4 |
| 3859 | 88 | 2016 | 5 |
| 1547 | 28 | 2016 | 6 |
| 831 | 17 | 2016 | 7 |
| 427 | 4 | 2016 | 8 |
| 512 | 13 | 2016 | 9 |
| 431 | 11 | 2016 | 10 |
| 1011 | 26 | 2016 | 11 |
| 791 | 15 | 2016 | 12 |
| 217 | 8 | 2017 | 1 |
| 490 | 17 | 2017 | 2 |
| 851 | 18 | 2017 | 3 |
| 1890 | 66 | 2017 | 4 |
| 2143 | 43 | 2017 | 5 |
| . | | | |
| . | | | |
| . | | | |
+-------+-------+-----------+------------+
This resultset count number of users and trips, my intention is actually to get an analysis of trips per user, like so:
+------+-------------+
| user | no_of_trips |
+------+-------------+
| 1 | 489 |
| 2 | 400 |
| 3 | 12 |
| 4 | 102 |
| . | |
| . | |
| . | |
+------+-------------+
How do I do this, please?
You seem to just want aggregation by user_id:
SELECT s.user_id, COUNT(distinct t.trip_id) as trips
FROM trips t INNER JOIN
session s
ON s.session_id = ANY(t.session_ids)
GROUP BY s.user_id ;
I'm pretty sure that the COUNT(DISTINCT) is unnecessary, so I would advise removing it:
SELECT s.user_id, COUNT(*) as trips
FROM trips t INNER JOIN
session s
ON s.session_id = ANY(t.session_ids)
GROUP BY s.user_id ;

SQL subcategory total is not properly placed at the end of every parent category

I am having trouble in SQl query,The query result should be like this
+------------+------------+-----+------+-------+--+--+--+
| District | Tehsil | yes | no | Total | | | |
+------------+------------+-----+------+-------+--+--+--+
| ABBOTTABAD | ABBOTTABAD | 377 | 5927 | 6304 | | | |
| ABBOTTABAD | HAVELIAN | 112 | 2276 | 2388 | | | |
| ABBOTTABAD | Overall | 489 | 8203 | 8692 | | | |
| CHARSADDA | CHARSADDA | 289 | 3762 | 4051 | | | |
| CHARSADDA | SHABQADAR | 121 | 1376 | 1497 | | | |
| CHARSADDA | TANGI | 94 | 1703 | 1797 | | | |
| CHARSADDA | Overall | 504 | 6841 | 7345 | | | |
+------------+------------+-----+------+-------+--+--+--+
The overall total should be should be shown at the end of every parent category but now it is showing like this
+------------+------------+-----+------+-------+--+--+--+
| District | Tehsil | yes | no | Total | | | |
+------------+------------+-----+------+-------+--+--+--+
| ABBOTTABAD | ABBOTTABAD | 377 | 5927 | 6304 | | | |
| ABBOTTABAD | HAVELIAN | 112 | 2276 | 2388 | | | |
| ABBOTTABAD | Overall | 489 | 8203 | 8692 | | | |
| CHARSADDA | CHARSADDA | 289 | 3762 | 4051 | | | |
| CHARSADDA | Overall | 504 | 6841 | 7345 | | | |
| CHARSADDA | SHABQADAR | 121 | 1376 | 1497 | | | |
| CHARSADDA | TANGI | 94 | 1703 | 1797 | | | |
+------------+------------+-----+------+-------+--+--+--+
My query is sorting second column with respect to first column although order by query is applied on my first column. This is my query
select District as 'District', tName as 'tehsil',[1] as 'yes',[0] as 'no',ISNULL([1]+[0], 0) as "Total" from
(
select d.Name as 'District',
case when grouping (t.Name)=1 then 'Overall' else t.Name end as tName,
BoundaryWallAvailable,
count(*) as total from School s
INNER JOIN SchoolIndicator i ON (i.refSchoolID=s.SchoolID)
INNER JOIN Tehsil t ON (t.TehsilID=s.refTehsilID)
INNER JOIN district d ON (d.DistrictID=t.refDistrictID)
group by
GROUPING sets((d.Name, BoundaryWallAvailable), (d.Name,t.Name, BoundaryWallAvailable))
) B
PIVOT
(
max(total) for BoundaryWallAvailable in ([1],[0])
) as Pvt
order by District
P.S: BoundaryWall is one column through pivoting i am breaking it into Yes and No Column

How to check dates condition from one table to another in SQL

Which way we can use to check and compare the dates from one table to another.
Table : inc
+--------+---------+-----------+-----------+-------------+
| inc_id | cust_id | item_id | serv_time | inc_date |
+--------+---------+-----------+-----------+-------------+
| 1 | john | HP | 40 | 17-Apr-2015 |
| 2 | John | HP | 60 | 10-Jan-2016 |
| 3 | Nick | Cisco | 120 | 11-Jan-2016 |
| 4 | samanta | EMC | 180 | 12-Jan-2016 |
| 5 | Kerlee | Oracle | 40 | 13-Jan-2016 |
| 6 | Amir | Microsoft | 300 | 14-Jan-2016 |
| 7 | John | HP | 120 | 15-Jan-2016 |
| 8 | samanta | EMC | 20 | 16-Jan-2016 |
| 9 | Kerlee | Oracle | 10 | 2-Feb-2017 |
+--------+---------+-----------+-----------+-------------+
Table: Contract:
+-----------+---------+----------+------------+
| item_id | con_id | Start | End |
+-----------+---------+----------+------------+
| Dell | DE2015 | 1/1/2015 | 12/31/2015 |
| HP | HP2015 | 1/1/2015 | 12/31/2015 |
| Cisco | CIS2016 | 1/1/2016 | 12/31/2016 |
| EMC | EMC2016 | 1/1/2016 | 12/31/2016 |
| HP | HP2016 | 1/1/2016 | 12/31/2016 |
| Oracle | OR2016 | 1/1/2016 | 12/31/2016 |
| Microsoft | MS2016 | 1/1/2016 | 12/31/2016 |
| Microsoft | MS2017 | 1/1/2017 | 12/31/2017 |
+-----------+---------+----------+------------+
Result:
+-------+---------+---------+--------------+
| Calls | Cust_id | Con_id | Tot_Ser_Time |
+-------+---------+---------+--------------+
| 2 | John | HP2016 | 180 |
| 2 | samanta | EMC2016 | 200 |
| 1 | Nick | CIS2016 | 120 |
| 1 | Amir | MS2016 | 300 |
| 1 | Oracle | OR2016 | 40 |
+-------+---------+---------+--------------+
MY Query:
select count(inc_id) as Calls, inc.cust_id, contract.con_id,
sum(inc.serv_time) as tot_serv_time
from inc inner join contract on inc.item_id = contract.item_id
where inc.inc_date between '2016-01-01' and '2016-12-31'
group by inc.cust_id, contract.con_id
The result from inc table with filter between 1-jan-2016 to 31-Dec-2016 with
count of inc_id based on the items and its contract start and end dates .
If I understand correctly your problem, this query will return the desidered result:
select
count(*) as Calls,
inc.cust_id,
contract.con_id,
sum(inc.serv_time) as tot_serv_time
from
inc inner join contract
on inc.item_id = contract.item_id
and inc.inc_date between contract.start and contract.end
where
inc.inc_date between '2016-01-01' and '2016-12-31'
group by
inc.cust_id,
contract.con_id
the question is a little vague so you might need some adjustments to this query.
select
Calls = count(*)
, Cust = i.Cust_id
, Contract = c.con_id
, Serv_Time = sum(Serv_Time)
from inc as i
inner join contract as c
on i.item_id = c.item_id
and i.inc_date >= c.[start]
and i.inc_date <= c.[end]
where c.[start]>='20160101'
group by i.Cust_id, c.con_id
order by i.Cust_Id, c.con_id
returns:
+-------+---------+----------+-----------+
| Calls | Cust | Contract | Serv_Time |
+-------+---------+----------+-----------+
| 1 | Amir | MS2016 | 300 |
| 2 | John | HP2016 | 180 |
| 1 | Kerlee | OR2016 | 40 |
| 1 | Nick | CIS2016 | 120 |
| 2 | samanta | EMC2016 | 200 |
+-------+---------+----------+-----------+
test setup: http://rextester.com/WSYDL43321
create table inc(
inc_id int
, cust_id varchar(16)
, item_id varchar(16)
, serv_time int
, inc_date date
);
insert into inc values
(1,'john','HP', 40 ,'17-Apr-2015')
,(2,'John','HP', 60 ,'10-Jan-2016')
,(3,'Nick','Cisco', 120 ,'11-Jan-2016')
,(4,'samanta','EMC', 180 ,'12-Jan-2016')
,(5,'Kerlee','Oracle', 40 ,'13-Jan-2016')
,(6,'Amir','Microsoft', 300 ,'14-Jan-2016')
,(7,'John','HP', 120 ,'15-Jan-2016')
,(8,'samanta','EMC', 20 ,'16-Jan-2016')
,(9,'Kerlee','Oracle', 10 ,'02-Feb-2017');
create table contract (
item_id varchar(16)
, con_id varchar(16)
, [Start] date
, [End] date
);
insert into contract values
('Dell','DE2015','20150101','20151231')
,('HP','HP2015','20150101','20151231')
,('Cisco','CIS2016','20160101','20161231')
,('EMC','EMC2016','20160101','20161231')
,('HP','HP2016','20160101','20161231')
,('Oracle','OR2016','20160101','20161231')
,('Microsoft','MS2016','20160101','20161231')
,('Microsoft','MS2017','20170101','20171231');

SQL Group Results and Add them up based on product

I've got the following SQL which basically works out the costings etc for each item.
SELECT
L.LocID,
L.LocationName,
L.LocationSqrMtr,
L.LocationAddress,
L.LocationPostCode,
L.LocationContact,
I.SubPIDItemID,
I.SPID,
I.ProductID,
C.SubPIDCostID,
C.PricePerItem,
C.ManDayPerItem
FROM
dbo.SubPIDCosts AS C
INNER JOIN dbo.SubPIDItems AS I ON
C.ProductID = I.ProductID
RIGHT OUTER JOIN dbo.SubPIDLocations AS L ON
I.LocationID = L.LocID AND C.LocationID = L.LocID
WHERE C.SPID = 48
This returns:
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
| LocID | LocationName | LocationSqrMtr | LocationAddress | LocationPostCode | LocationContact | SubPIDItemID | SPID | ProductID | SubPIDCostID | PricePerItem | ManDayPerItem | | | | | | | | |
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
| 379 | | | Location | 1 | 1 | 345 | Generic | Building | Generic | Building | NULL | 158 | 48 | | | | 108 | 0.3400 | 6.17 |
| 379 | | | Location | 1 | 1 | 345 | Generic | Building | Generic | Building | NULL | 159 | 48 | 1 | 109 | 0.3400 | | .47 | |
| 379 | 3 | Location | 1 | 615 | Generic | Building | Generic | Building | NULL | 160 | 48 | | | | 110 | 0.7317 | 0.50 | | |
| 379 | 4 | Location | | | 615 | Generic | Building | Generic | Building | NULL | 161 | 48 | | | | 111 | 0.7317 | 0.50 | |
| 379 | 4 | Location | | | 615 | Generic | Building | Generic | Building | NULL | 16 | | 48 | 1 | 11 | | 0.7317 | 0.50 | |
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
But what I would like to do is group it by the product ID. So all the ones that are ProductID 22 it should add the values up for ManDayPerItem and PricePerItem and LocationSqrMtr
It's used in the following context
I'd like to have them grouped nicely in that list.
As you said, group by:
SELECT ProductID, SUM(ManDayPerItem), SUM(PricePerItem), SUM(LocationSqrMtr)
FROM
dbo.SubPIDCosts AS C
INNER JOIN dbo.SubPIDItems AS I ON
C.ProductID = I.ProductID
RIGHT OUTER JOIN dbo.SubPIDLocations AS L ON
I.LocationID = L.LocID AND C.LocationID = L.LocID
WHERE C.SPID = 48
GROUP BY ProductID;