How to add sum value to every row? - sql-server

Below is my table:
id order_number order_date order_details
---------------------------------------------
1 222 01-01-2020 44
2 222 02-01-2020 66
3 222 03-01-2020 20
4 223 03-01-2020 33
5 224 04-01-2020 55
6 225 02-01-2020 77
I want to have sum(order_details) where order_number = 222
like this table
order_date sum_order_details
----------------------------------
01-01-2020 130
02-01-2020 130
03-01-2020 130
I tried the below but it doesn't work
select order_number , order_date , sum(order_details) sum_orders from ex
group by order_number
having order_number = 222

It seems like you're after this is a windowed SUM:
SELECT order_date,
SUM(order_details) OVER () AS sum_orders
FROM YourTable
WHERE order_number = 222;

Related

SQL Server Table Column from data

I'm trying to achieve sort of solution to the below table, as I need to make one of the rows in column as column
sku title name product_qty ID warehouse_id
-----------------------------------------------------
S001 Title 1 warehouse1 5 23 1
S001 Title 1 warehouse2 95 23 2
S001 Title 1 warehouse3 3 23 3
S002 Title 2 warehouse1 1 24 1
S002 Title 2 warehouse2 91 24 2
S002 Title 2 warehouse3 0 25 3
and what I would like to achieve
sku title name
warehouse 1 warehouse 2 warehouse 3
S001 Title 1 5 95 3
S002 Title 2 1 91 0
Please try this ... solution...You need to pivot the data.
CREATE TABLE Pivots
(
sku VARCHAR(10)
,title VARCHAR(10)
,name VARCHAR(10)
,product_qty INT
,ID INT
,warehouse_id INT
)
GO
INSERT INTO Pivots VALUES
('S001','Title1','warehouse1',5 , 23 , 1),
('S001','Title1','warehouse2',95 , 23 , 2),
('S001','Title1','warehouse3',3 , 23 , 3),
('S002','Title2','warehouse1',1 , 24 , 1),
('S002','Title2','warehouse2',91 , 24 , 2),
('S002','Title2','warehouse3',0 , 25 , 3)
GO
SOLUTION
SELECT sku,title titlename,ISNULL(MAX(x.warehouse1),0) warehouse1
,ISNULL(MAX(x.warehouse2),0) warehouse2 ,ISNULL(MAX(x.warehouse3),0) warehouse3 FROM Pivots p
PIVOT
(
MAX(product_qty) FOR name IN ([warehouse1],[warehouse2],[warehouse3])
)x
GROUP BY sku,title
OUTPUT
sku titlename warehouse1 warehouse2 warehouse3
---------- ---------- ----------- ----------- -----------
S001 Title1 5 95 3
S002 Title2 1 91 0
(2 rows affected)
SOLUTION 2 - USING conditional aggregation
SELECT sku,title titlename
,ISNULL(MAX(CASE WHEN name = 'warehouse1' THEN product_qty END),0) warehouse1
,ISNULL(MAX(CASE WHEN name = 'warehouse2' THEN product_qty END),0) warehouse2
,ISNULL(MAX(CASE WHEN name = 'warehouse3' THEN product_qty END),0) warehouse3
FROM Pivots p
GROUP BY sku,title
OUTPUT
sku titlename warehouse1 warehouse2 warehouse3
---------- ---------- ----------- ----------- -----------
S001 Title1 5 95 3
S002 Title2 1 91 0
(2 rows affected)

Max Nbr of Months W/ No Activity in Past 12 Months

I have a data set that contains the following items:
Month-Yr
Account Nbr
Revenue Total
If an account does not have a revenue total for a given month there is no record for that account / month.
I would like to know per account - what is the maximum # of consecutive months that account had no revenue for?
For example if account 123 had revenue in every month in the last 12 their count would be 0.
If account 987 had revenue for 4 consecutive months then no revenue for 5 consecutive months and then revenue for the remaining months their count would be 5.
If account 657 had activity every other month then their count would be 1, b/c 1 is the max # of consecutive months with no activity.
Thanks in advance
SAMPLE DATA
**Accnt** |**Month-Yr** |**Revenue**
123 |8/1/2016 |1000
123 |9/1/2016 |1500
123 |10/1/2016 |500
123 |11/1/2016 |100
123 |12/1/2016 |250
123 |1/1/2017 |750
123 |2/1/2017 |900
123 |3/1/2017 |700
123 |4/1/2017 |1200
123 |5/1/2017 |250
123 |6/1/2017 |750
123 |7/1/2017 |900
123 |8/1/2017 |700
123 |9/1/2017 |1200
987 |8/1/2016 |100
987 |9/1/2016 |250
987 |10/1/2016 |750
987 |11/1/2016 |900
987 |5/1/2017 |700
987 |6/1/2017 |1300
987 |7/1/2017 |250
987 |8/1/2017 |750
987 |9/1/2017 |900
657 |8/1/2016 |700
657 |10/1/2016 |1200
657 |12/1/2016 |100
657 |2/1/2017 |250
657 |4/1/2017 |750
657 |6/1/2017 |900
657 |8/1/2017 |700
Accnt 123 would be 0 months
Accnt 987 would be 5 months
Accnt 657 would be 1 month
How about this one? (Because you posted minimal info, I reserve the right to create my own DDL as I interpret).
IF OBJECT_ID ('tempdb..#') IS NOT NULL
DROP TABLE #sales
GO
CREATE TABLE #sales
(Dte datetime
,amt int
,id int
,rownum int identity PRIMARY KEY
)
INSERT INTO #sales
SELECT '9/1/17',1200, 987
INSERT INTO #sales
SELECT '10/1/17',1100, 987
INSERT INTO #sales
SELECT '11/1/17',1000, 987
INSERT INTO #sales
SELECT '5/1/18',1900, 987
INSERT INTO #sales
SELECT '6/1/18',120, 987
INSERT INTO #sales
SELECT '4/1/17',100, 657
INSERT INTO #sales
SELECT '5/1/17',190, 657
INSERT INTO #sales
SELECT '7/1/17',12, 657
GO
SELECT MAX(DATEDIFF(dd,a.dte,b.dte)), a.id
FROM #sales a
INNER JOIN #sales b
ON a.rownum = b.rownum-1
AND a.id =b.id
GROUP BY a.id

Determine 'active' records

I have a list of customers that can have a single, or multiple, service listed. In the table that houses the changes over time there is an indicator of 'Added' or 'Removed'.
What I need: determine those service(s) that are currently active, if at all.
Here is a sample set of data:
CUST_ID SRV_ID STATUS ACTION_DATE
12345 102 Added 1/31/17 10:15
12345 189 Added 4/18/17 15:37
12345 189 Removed 4/21/17 14:08
12345 194 Added 5/2/17 14:43
12345 194 Removed 5/5/17 10:02
12345 194 Added 5/5/17 13:06
12345 69 Added 4/19/17 9:36
12345 69 Removed 5/2/17 14:43
12345 73 Added 4/20/17 10:21
12345 73 Removed 4/25/17 11:20
12345 95 Added 5/4/17 9:48
12345 95 Removed 5/4/17 10:05
Records to be returned: 102 on 1/31/17 10:15 and 194 on 5/5/17 13:06
You can find the latest row for each cust_id and serv_id using top 1 with ties and window function row_number and then filter those with status "Added":
select *
from (
select top 1
with ties *
from your_table
order by row_number() over (
partition by cust_id, srv_id
order by action_date desc
)
) t
where status = 'Added'
Produces:
CUST_ID SRV_ID STATUS ACTION_DATE
12345 102 Added 2017/01/31 10:15
12345 194 Added 2017/05/05 13:06
Demo
Like this:
SELECT SRV_ID
FROM YourTable
GROUP BY SRV_ID
HAVING MAX(CASE WHEN STATUS='Added' THEN ACTION_DATE END)
> MAX(CASE WHEN STATUS='Removed' THEN ACTION_DATE END)

Grouping rows to minimise deviation

I have a Employee Wages table like this, with their EmpID and their wages.
EmpId | Wages
================
101 | 1280
102 | 1600
103 | 1400
104 | 1401
105 | 1430
106 | 1300
I need to write a Stored Procedure in SQL Server, to group the Employees according to their wages, such that similar salaried people are in groups together and the deviations within the group is as minimum as possible.
There are no other conditions or rules mentioned.
The output should look like this
EmpId | Wages | Group
=======================
101 | 1280 | 1
106 | 1300 | 1
103 | 1400 | 2
104 | 1401 | 2
105 | 1430 | 2
102 | 1600 | 3
You can use a query like the following:
SELECT EmpId, Wages,
DENSE_RANK() OVER (ORDER BY CAST(Wages - t.min_wage AS INT) / 100) AS grp
FROM mytable
CROSS JOIN (SELECT MIN(Wages) AS min_wage FROM mytable) AS t
The query calculates the distance of each wage from the minimum wage and then uses integer division by 100 in order to place records in slices. So all records that have a deviation that is between 0 - 99 off the minimum wage are placed in the first slice. The second slice contains records off by 100 - 199 from the minimum wage, etc.
You can for +-30 deviation as the below:
DECLARE #Tbl TABLE (EmpId INT, Wages INT)
INSERT INTO #Tbl
VALUES
(99, 99),
(100, 101),
(101, 1280),
(102, 1600),
(103, 1400),
(104, 1401),
(105, 1430),
(106, 1300)
;WITH CTE AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY Wages) AS RowId FROM #Tbl )
SELECT
A.EmpId ,
A.Wages ,
DENSE_RANK() OVER (ORDER BY MIN(B.RowId)) [Group]
FROM
CTE A CROSS JOIN CTE B
WHERE
ABS(B.Wages - A.Wages) BETWEEN 0 AND 30 -- Here +-30
GROUP BY A.EmpId, A.Wages
ORDER BY A.Wages
Result:
EmpId Wages Group
----------- ----------- --------------------
99 99 1
100 101 1
101 1280 2
106 1300 2
103 1400 3
104 1401 3
105 1430 3
102 1600 4

Oracle based PIVOT with multiple columns group

Using the following tables,
Productivity:
PRODUCTIVITYID PDATE EMPLOYEEID ROOMID ROOMS_SOLD SCR
81 03/26/2016 7499 21 56 43
82 03/26/2016 7566 42 - -
102 03/26/2016 7499 22 434 22
101 03/26/2016 7566 21 43 53
ProductivityD:
PRODUCTIVITYID WORKHRS MEALPANELTY DESCRIPTION
2 50 4 -
21 6.4 1 -
102 6 - -
81 1.32 - -
101 3.6 - -
Rooms:
ID ROOM PROPERTCODE
22 102 6325
41 103 6325
42 104 6325
43 105 6325
EMP:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7566 JONES MANAGER 7839 04/02/1981 2975 - 20
7788 SCOTT ANALYST 7566 12/09/1982 3000 - 20
7902 FORD ANALYST 7566 12/03/1981 3000 - 20
7369 SMITH CLERK 7902 12/17/1980 800 - 20
7499 ALLEN SALESMAN 7698 02/20/1981 1600 300 30
The following query is generating below output but I need to group employees and sum workhrs and then pivot RM_ROOM and RM_SCR
WITH pivot_data AS (
SELECT eNAME,workhrs,room, 'RM' as RM,SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID
)
SELECT *
FROM pivot_data
PIVOT (
MIN(room) as room,min(scr) as SCR --<-- pivot_clause
FOR RM--<-- pivot_for_clause
IN ('RM') --<-- pivot_in_clause
)
Current Output:
ENAME WORKHRS 'RM'_ROOM 'RM'_SCR
JONES 3.6 101 53
ALLEN 6 102 22
ALLEN 1.32 101 43
Desired Output:
ENAME WORKHRS 'RM'_ROOM 'RM'_SCR 'RM'_ROOM 'RM'_SCR
JONES 3.6 101 53 - -
ALLEN 7.32 101 43 102 22
You are pivoting on a fixed value, the string literal 'RM', so you're really not doing anything useful in the pivot - the output is the same as you'd get from running the 'pivot_data' query on its own:
SELECT eNAME,workhrs,room, SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID;
ENAME WORKHRS ROOM SCR
----- ---------- ---------- ----------
JONES 3.6 101 53
ALLEN 1.32 101 43
ALLEN 6 102 22
You want the aggregate workhrs for each employee, and a pivot of the rooms they sold. If you change that query to get the analytic sum of workhrs and a ranking of the room/scr values (and using modern join syntax) you get:
select e.ename, r.room, p.scr,
sum(d.workhrs) over (partition by e.ename) as wrkhrs,
rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid;
ENAME ROOM SCR WRKHRS RNK
----- ---------- ---------- ---------- ----------
ALLEN 101 43 7.32 1
ALLEN 102 22 7.32 2
JONES 101 53 3.6 1
You can then pivot on that generated rnk number:
with pivot_data as (
select e.ename, r.room, p.scr,
sum(d.workhrs) over (partition by e.ename) as wrkhrs,
rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid
)
select *
from pivot_data
pivot (
min(room) as room, min(scr) as scr --<-- pivot_clause
for rnk --<-- pivot_for_clause
in (1, 2, 3) --<-- pivot_in_clause
);
ENAME WRKHRS 1_ROOM 1_SCR 2_ROOM 2_SCR 3_ROOM 3_SCR
----- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ALLEN 7.32 101 43 102 22
JONES 3.6 101 53
You need to know the maximum number of rooms any employee may have - i.e. the highest rnk could ever be - and include all of those in the in clause. Which means you're likely to end up with empty columns, as in this example where there is no data for 3_room or 3_scr. You can't avoid that though, unless you get an XML result or generate the query dynamically.
What you are saying makes no sense. What do you mean by "pivot RM_ROOM"? So I have to guess. I am guessing you want to group employees and sum workhrs, and then pivot the result. The "Output" you show seems to be the output for pivot_data, your subquery.
Your answer will only have eNAME and for each of them, a count of hours worked. So you don't need to SELECT the room numbers in the pivot_data subquery. You only need eNAME and workhrs. Then it is a simple matter of using the PIVOT syntax:
WITH pivot_data AS (
SELECT eNAME, workhrs FROM PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID
)
SELECT *
FROM pivot_data
PIVOT (
SUM(workhrs)
FOR eNAME IN ('JONES', 'ALLEN')
)
/
Output:
'JONES' 'ALLEN'
---------- ----------
3.6 7.32

Resources