Update table column with value from inner query? - sql-server

I have the following table:
create table public.dctable
(
prod int,
customer varchar(100),
city varchar(100),
num int,
tim datetime,
dc smallint
);
insert into dctable
values (1, 'Jim', 'Venice', 5, '2015-08-27 1:10:00', 0),
(1, 'Jim', 'Venice', 5, '2015-08-27 1:10:15', 0),
(1, 'Jim', 'Venice', 5, '2015-08-27 1:10:28', 0),
(4, 'Jane', 'Vienna', 8, '2018-06-04 2:20:43', 0),
(4, 'Jane', 'Vienna', 8, '2018-06-04 2:20:45', 0),
(4, 'Jane', 'Vienna', 8, '2018-06-04 2:20:49', 0),
(4, 'Jane', 'Vienna', 8, '2018-06-04 2:30:55', 0),
(7, 'Jack', 'Vilnius', 4, '2015-09-15 2:20:55', 0),
(7, 'Jake', 'Vigo', 9, '2018-01-01 10:20:05', 0),
(7, 'Jake', 'Vigo', 2, '2018-01-01 10:20:25', 0);
Now I want to update the column dc to the value of tdc in this query:
select
t.*,
(case
when lead(tim) over (partition by prod, customer, city, num order by tim) <= dateadd(second, 30, tim)
then 1
else 0
end) as tdc
from
public.dctable t
So I have tried this:
update public.dctable
set dc = b.tdc
from
(select
t.*,
(case
when lead(tim) over (partition by prod, customer, city, num order by tim) <= dateadd(second, 30, tim)
then 1
else 0
end) as tdc
from
public.dctable t) b
where
public.dctable.prod = b.prod
and public.dctable.customer = b.customer
and public.dctable.city = b.city
and public.dctable.num = b.num;
But when I query the results, dc is still 0 for all rows.
select * from public.dctable;
prod customer city num tim dc
-------------------------------------------------------------
1 Jim Venice 5 2015-08-27 01:10:00 0
1 Jim Venice 5 2015-08-27 01:10:28 0
1 Jim Venice 5 2015-08-27 01:10:15 0
4 Jane Vienna 8 2018-06-04 02:20:49 0
4 Jane Vienna 8 2018-06-04 02:20:45 0
4 Jane Vienna 8 2018-06-04 02:30:55 0
4 Jane Vienna 8 2018-06-04 02:20:43 0
7 Jake Vigo 2 2018-01-01 10:20:25 0
7 Jack Vilnius 4 2015-09-15 02:20:55 0
7 Jake Vigo 9 2018-01-01 10:20:05 0
How can I get it to update the column dc to the value of tdc from the inner query above?
Thanks

This seems to be what you want.
SQL Fiddle
update d
set d.dc = b.dc2
from dctable d
inner join
(select
*,
dc2 = case
when lead(tim) over (partition by prod, customer, city, num order by tim) <= dateadd(second, 30, tim)
then 1
else 0
end
from dctable) b on
d.prod = b.prod
and d.customer = b.customer
and d.city = b.city
--and d.tim = b.tim --you may also want this join clause.
and d.num = b.num;
select * from dctable

Related

SQL Server - select and join parent-child records, pivot and group

The real problem is probably less complex than the subject might suggest.
The schema
Three tables (simplified). There can be multiple people within one membership. The main member is identified as 1 in person_membership.relationship, there can be a spouse of the main member identified as '2' and other dependants (any other number).
CREATE TABLE person
([first_name] varchar(10), [surname] varchar(10), [date_of_birth] date, [person_id] int);
INSERT INTO person
([first_name], [surname], [date_of_birth] ,[person_id])
VALUES
('Alice', 'AA', '1/1/1990', 1),
('Bob' , 'AA', '1/1/1990', 2),
('Carol', 'AA', '1/1/1990', 3),
('Dave' , 'AA', '1/1/1990', 4),
('Elen' , 'AA', '1/1/1990', 5),
('Fran' , 'BB', '1/1/1990', 6),
('Gaby' , 'BB', '1/1/1990', 7)
CREATE TABLE person_membership
([person_id] int, [status_flag] varchar(1), [membership_id] int, [relationship] int);
INSERT INTO person_membership
([person_id], [status_flag], [membership_id], [relationship])
VALUES
(1, 'A', 10, 1),
(2, 'A', 10, 2),
(3, 'A', 10, 3),
(4, 'A', 10, 4),
(5, 'A', 10, 4),
(6, 'A', 20, 1),
(7, 'A', 20, 3);
CREATE TABLE memship
([membership_id] int, [memship_status] varchar(1));
INSERT INTO memship
([membership_id], [memship_status])
VALUES
(10, 'A'),
(20, 'A');
The task
Simplified version - display membership and person id of the main member and identify if they have a spouse, and also if they have any dependants show how many of them they are.
The desired output
The basic version something like the screenshot below. Main member ID, their person ID, Yes/No field for spouse, number of dependants:
The current solution
The code below works and creates the desired output but it seems very clunky. There must be more elegant ways of doing it?
WITH peeps AS (SELECT person.person_id,
person.first_name,
person.surname,
person_membership.membership_id,
person_membership.relationship
FROM memship, person, person_membership
WHERE person_membership.person_id = person.person_id
AND memship.membership_id = person_membership.membership_id
AND person_membership.status_flag='A'
AND memship.memship_status='A')
SELECT final.MemID, final.PersonID, sum(final.Spouse) as 'Spouse?', sum(final.Kids) as 'No of kids'
FROM (
SELECT
peeps1.membership_id AS 'MemID',
CASE peeps1.relationship
WHEN 1 THEN peeps1.person_id
ELSE peeps2.person_id
END AS 'PersonID',
SUM (CASE WHEN
peeps1.relationship = 2 THEN 1
ELSE 0
END ) AS 'Spouse',
SUM (CASE WHEN
peeps1.relationship > 2 THEN 1
ELSE 0
END ) AS 'Kids'
FROM peeps peeps1
INNER JOIN peeps peeps2 ON peeps2.membership_id = peeps1.membership_id AND peeps2.relationship = 1
GROUP BY peeps1.membership_id, peeps1.relationship, peeps1.person_id, peeps2.person_id) as final
GROUP BY final.MemID, final.PersonID
Try This
FIDDLE DEMO
SELECT M.membership_id,
MAX(CASE WHEN PM.relationship = 1 THEN P.person_id ELSE NULL END) person_id,
SUM (CASE WHEN PM.relationship = 2 THEN 1 ELSE 0 END )AS 'Spouse',
SUM (CASE WHEN PM.relationship > 2 THEN 1 ELSE 0 END ) AS 'Kids'
FROM memship M
JOIN person_membership PM ON M.membership_id = PM.membership_id
JOIN person P ON PM.person_id = P.person_id
WHERE PM.status_flag='A' AND M.memship_status='A'
GROUP BY M.membership_id
Simplified query
SELECT MemID = pm.membership_id,
PersonID = MAX (CASE WHEN pm.relationship = 1 THEN p.person_id END),
[Spouce?] = SUM (CASE WHEN pm.relationship = 2 THEN 1 ELSE 0 END),
[No of kids] = SUM (CASE WHEN pm.relationship NOT IN (1, 2) THEN 1 ELSE 0 END)
FROM person p
INNER JOIN person_membership pm ON p.person_id = pm.person_id
INNER JOIN memship m ON pm.membership_id = m.membership_id
WHERE pm.status_flag = 'A'
AND m.memship_status = 'A'
GROUP BY pm.membership_id
Note : please avoid using old style of join. User INNER JOIN instead
SELECT M.membership_id,
MAX(CASE WHEN PM.relationship = 1 THEN P.person_id ELSE NULL END) person_id,
COUNT(CASE WHEN PM.relationship = 2 THEN 1 ELSE 0 END )AS 'Spouse',
COUNT(CASE WHEN PM.relationship IN (3, 4, 5) THEN 1 ELSE 0 END ) AS 'Kids'
FROM memship M
JOIN person_membership PM ON M.membership_id = PM.membership_id
JOIN person P ON PM.person_id = P.person_id
WHERE PM.status_flag='A' AND M.memship_status='A'
GROUP BY M.membership_id

distribution of income over time based on rule set

Not sure if I was able to properly describe the title of my question but I haven't done anything this complex in T-Sql. Here's what I'm trying to achieve.
After several queries and table building, I got the data (below) in a temp table which probably will become a permanent table.
The part I need help with is, Need to create another table to report part of the sale from the data below.
Table 1
LOC# ITEM sale_total FiscalYear FiscalPrd TYPE O_R DESC LFT_EXP METHOD PRD_MO AG_PCNT PLAN_ID YEARS STATUS
33 17879 12203.57 2017 3 A O Plan A L W 120 100.00 6 10 N
33 17903 579.97 2017 3 A O Plan A L W 120 100.00 6 10 N
33 18870 799.60 2017 3 A O Plan A L W 120 100.00 6 10 N
33 19739 319.95 2017 3 A B Plan C E F 36 100.00 8 3 N
33 21585 559.96 2017 3 B O Plan B E N 0 100.00 10 0 N
A percentage of the sale_total from table above needs to be distributed based on the table below (I can also include the YR01-YR10 columns in the table above if it make things simpler).
Table 2
PLAN_ID EFDATE MONTHS METHOD EPERCENT YR01 YR02 YR03 YR04 YR05 YR06 YR07 YR08 YR09 YR10
6 2007-08-01 120 W 100.00 40.00 20.00 11.00 8.00 6.00 5.00 4.00 3.00 2.00 1.00
8 2012-11-12 36 F 100.00 33.00 33.00 34.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
10 2015-10-01 0 N 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
So my end result would look like below for LOC#33 and item 18870: (So the calculation is based on the plan. For this specific example, item 18870 falls under plan 6 (table 1). Table 2 has the distribution of all plans. We can see it spreads over 120 months and YR01-YR10 has the yearly percent distribution. Now from the sales number for 18870 from table 1, 799.60, distribution math for year 1 is (799.60 x 0.4) / 12 = 26.65. Same method follows up to year 10 for this plan and up to year 3 for plan 8. For the 10 year plan, it will create 120 input records. 1 for each month for each item, location)
LOC# ITEM FiscalYear FiscalPrd SALES
33 18870 2017 4 26.65
33 18870 2017 5 26.85
33 18870 2017 6 26.85
.............................................
.............................................
33 18870 2017 11 26.85
33 18870 2017 12 26.85
33 18870 2018 1 13.33
33 18870 2018 2 13.33
.............................................
.............................................
33 18870 2018 11 13.33
33 18870 2018 12 13.33
.............................................
.............................................
33 18870 2027 2 0.67
33 18870 2027 3 0.67
It will distribute that income over 120 months at the percentage dictated by the table 2 for planID 6. for planID 8, it will do the same math over 36 months.
The percentages can change over time and a user will manage the plans. There are other locations and the first table will include all location for the current fiscal period and all items (3 max as shows in Table 2). I created a status columns so I can mark if once the data is processed.
When comes the next fiscal period sales, the program will update the above result set sales numbers to include new sales. It will be run once a month to generate the above result.
Would greatly appreciate some direction as I got up to this point and not sure how to approach from here.
Thanks a bunch.
#ZLK I saved the first run in a temp table, then added the following rows
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 18870, 800.00, 2017, 4, 6, 10),
(33, 19739, 300.00, 2017, 4, 8, 3),
(33, 21585, 500.00, 2017, 4, 10, 0);
This the save first set of item, location with different sales number in fiscal period 4. the first set was inserted into a table #finalDist, the second uses the following query to insert and update.
begin tran
if exists (select * FROM #finalDist AGE
INNER JOIN #dist PrdAg on PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FiscalYear
and PrdAg.FiscalPrd = AGE.FiscalPrd)
begin
UPDATE AGE
SET AGE.SALES = AGE.SALES + PrdAg.SALES
FROM #finalDist AGE
INNER JOIN #dist PrdAg on PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FiscalYear
and PrdAg.FiscalPrd = AGE.FiscalPrd
end
else
begin
INSERT INTO #finalDist (Loc, Item, FiscalYear, FiscalPrd, SALES)
SELECT Loc, Item, FiscalYear, FiscalPrd, SALES from #dist PrdAg
WHERE NOT EXISTS (SELECT AGE.Item FROM #finalDist AGE WHERE PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FISCALYear
and PrdAg.FiscalPrd = AGE.FiscalPrd)
end
commit tran
I realize I can't do if else as I need to do both insert and update. It will update everything except the fiscal period 3, then it will insert four rows for this case
Loc Item FiscalYear FiscalPrd SALES
33 18870 2027 4 0.66666666666
33 19739 2020 4 8.50000000000
33 17903 2027 4 0.41666666666
33 17879 2027 4 8.33333333333
update look like this
33 17879 2017 4 406.78566666666 -- this row wasn't updated
33 17879 2017 5 740.11899999999
One way you can do it is like this:
DECLARE #T TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #T (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0);
DECLARE #T2 TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #T2 (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM CTE AS A CROSS JOIN CTE) -- Numbers 1-121
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, DATEFROMPARTS(T.FiscalYear, T.FiscalPrd, 1))),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, DATEFROMPARTS(T.FiscalYear, T.FiscalPrd, 1))),
SALES = T.Sales_Total * C.Vals / 100 / 12
FROM #T AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #T2 AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = (CTE2.N + 11) / 12
ORDER BY T.Loc, T.Item, CTE2.N;
Essentially you want to get a list of numbers (up to 120 here but if there's more than 10 years, you would need more) and cross join it to your table. Then unpivot the values in table2 and link them to the numbers table in (grouping them by years).
EDIT:
Taking into account that values can change and assuming the end date is still the same and doesn't increase, this is what I believe you're looking for:
DECLARE #T TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #T (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0),
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 21585, 500.00, 2017, 4, 10, 0),
(33, 17879, 5000.00, 2017, 5, 6, 10),
(33, 17879, 6900.00, 2017, 7, 6, 10);
DECLARE #T2 TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #T2 (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM CTE AS A CROSS JOIN CTE) -- Numbers 0-120
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, T.FirstDate)),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, T.FirstDate)),
SALES = T.TotalToDate * C.Vals / 100 / 12
FROM
(
SELECT T.Loc,
T.Item,
T.YEARS,
T.Plan_ID,
C.TotalToDate,
FirstDate = CAST(DATEADD(MONTH, 1, CAST(MIN(FiscalYear) OVER (PARTITION BY Loc, Item) AS CHAR(4)) + '-' +
CAST(MIN(FiscalPrd) OVER (PARTITION BY Loc, Item) AS VARCHAR(2)) + '-01') AS DATE),
CurrentDate = CAST(DATEADD(MONTH, 1, CAST(FiscalYear AS CHAR(4)) + '-' + CAST(FiscalPrd AS VARCHAR(2)) + '-01') AS DATE),
C2.NextDate
FROM #T AS T
CROSS APPLY
(
SELECT SUM(Sales_Total)
FROM #T
WHERE Loc = T.Loc
AND Item = T.Item
AND FiscalYear * 12 + FiscalPrd <= T.FiscalYear * 12 + T.FiscalPrd
) AS C(TotalToDate)
OUTER APPLY
(
SELECT CAST(DATEADD(MONTH, 1, CAST(MIN(FiscalYear) AS CHAR(4)) + '-' +
CAST(MIN(FiscalPrd) AS VARCHAR(2)) + '-01') AS DATE)
FROM #T
WHERE Loc = T.Loc
AND Item = T.Item
AND FiscalYear * 12 + FiscalPrd > T.FiscalYear * 12 + T.FiscalPrd
) AS C2(NextDate)
) AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12 - 1
AND CTE2.N >= DATEDIFF(MONTH, T.FirstDate, T.CurrentDate)
AND DATEADD(MONTH, CTE2.N, T.FirstDate) < COALESCE(T.NextDate, DATEADD(MONTH, T.YEARS * 12, T.FirstDate))
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #T2 AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = (CTE2.N + 12) / 12
ORDER BY T.Loc, T.Item, CTE2.N;
SECOND EDIT (Modified to have the start date be the month declared, e.g. March 2017 means the plan starts in March 2017 instead of April 2017. The only difference is adjusting the row_number joins):
/*
#PlanTable: A static table for plans.
*/
DECLARE #PlanTable TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #PlanTable (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
/*
#RecordsToInsert: The values you're inserting into your final table. Starting with FiscalYear 2017 and FiscalPrd 3 as an example.
*/
DECLARE #RecordsToInsert TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #RecordsToInsert (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0);
/*
#FinalTable: This is the table you're using to insert the data.
*/
DECLARE #FinalTable TABLE (Loc INT, Item INT, FiscalYear INT, FiscalPrd INT, SALES DECIMAL(10, 2));
/*
Start by inserting the first lot of information into the final table.
*/
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM CTE AS A CROSS JOIN CTE) -- Numbers 0-120
INSERT #FinalTable (Loc, Item, FiscalYear, FiscalPrd, SALES)
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, CAST(T.FiscalYear AS CHAR(4)) + '-' + CAST(T.FiscalPrd AS VARCHAR(2)) + '-01')),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, CAST(T.FiscalYear AS CHAR(4)) + '-' + CAST(T.FiscalPrd AS VARCHAR(2)) + '-01')),
SALES = T.Sales_Total * C.Vals / 100 / 12
FROM #RecordsToInsert AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12 - 1
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #PlanTable AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = CTE2.N / 12 + 1
ORDER BY T.Loc, T.Item, CTE2.N;
/*
Next we want to insert records for the next FiscalPrd, so we get rid of the last ones and put in FiscalYear 2017, FiscalPrd 4.
*/
DELETE #RecordsToInsert;
INSERT #RecordsToInsert (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 18870, 800.00, 2017, 4, 6, 10),
(33, 19739, 300.00, 2017, 4, 8, 3),
(33, 21585, 500.00, 2017, 4, 10, 0);
/*
Then we update the final table with the new sales total, ignoring periods that were prior to the fiscal year and period being inserted.
*/
UPDATE T
SET SALES = SALES_NEW
FROM (
SELECT FT.Loc,
FT.Item,
FT.FiscalYear,
FT.FiscalPrd,
FT.SALES,
SALES_NEW = (SUM(FT.SALES) OVER (PARTITION BY FT.Loc, FT.Item) + R.Sales_Total) * C.Vals / 100 / COUNT(1) OVER (PARTITION BY FT.Loc, FT.Item, (FT.RN + 11) / 12)
FROM (SELECT *, RN = ROW_NUMBER() OVER (PARTITION BY Loc, Item ORDER BY FiscalYear, FiscalPrd) FROM #FinalTable) AS FT
JOIN #RecordsToInsert AS R
ON R.Loc = FT.Loc
AND R.Item = FT.Item
AND R.FiscalYear * 12 + R.FiscalPrd <= FT.FiscalYear * 12 + FT.FiscalPrd
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #PlanTable AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = R.PLAN_ID
AND C.Y = (FT.RN + 11) / 12
) T;
/*
For the first year, the sales for 2017/5 onwards have changed to (totalsales - firstmonth) * 40% / 11
For the second years onward, the sales have changed to totalsales * whatever% / 12
The first month of the first year remains the same.
*/
SELECT Loc, Item, FiscalYear, FiscalPrd, SALES
FROM #FinalTable
ORDER BY Loc, Item, FiscalYear, FiscalPrd;

SQL query to get Map Id on passing Id value

Id InvID InvDate OriginalInvID FilterDesc
1 1 2017-03-01 00:00:00.000 0 First Inv Created
2 2 2017-03-06 00:00:00.000 1 Link ID
3 3 2017-03-01 00:00:00.000 0 First Inv Created
4 4 2017-03-03 00:00:00.000 3 Link ID
5 5 2017-03-06 00:00:00.000 4 Second Inv Created on top of MapID
6 6 2017-03-01 00:00:00.000 0 First Inv Created
7 7 2017-03-03 00:00:00.000 6 Link ID
8 8 2017-03-05 00:00:00.000 7 Second In Created on top of Map Id
9 9 2017-03-06 00:00:00.000 8 Second Inv Created on top of Map Id
Hi, in above table I have to pass invId and I need result with map Id who is in OriginalInvID column.
For example:
If I pass 1 then I get 1 & 2 invId
If i pass 4 then I get 3,4,5
If i pass 8 then I get 6,7,8,9 like this way
If I understood what you want, I think you wanted a query like this:
declare #InvId int = 8;
with cte(Id, InvID, InvDate, OriginalInvID) as (
select *
from yourTable
where OriginalInvID = #InvId
union all
select t.*
from yourTable t join cte on t.InvId = cte.OriginalInvID
)
select *
from cte
order by Id;
You can use a while loop to fetch father and children nodes storing them in temp tables:
declare #myInvId int
declare #father_counter int
declare #children_counter int
declare #temp table (Id int, InvID int, InvDate datetime, OriginalInvID int, FilterDesc nvarchar(100))
declare #fathers table(id int, status int)
declare #children table(id int, status int)
insert into #temp
select 1, 1, '2017-03-01 00:00:00.000', 0, 'First Inv Created'
union all select 2, 2, '2017-03-06 00:00:00.000', 1, 'Link ID'
union all select 3, 3, '2017-03-01 00:00:00.000', 0, 'First Inv Created'
union all select 4, 4, '2017-03-03 00:00:00.000', 3, 'Link ID'
union all select 5, 5, '2017-03-06 00:00:00.000', 4, 'Second Inv Created on top of MapID'
union all select 6, 6, '2017-03-01 00:00:00.000', 0, 'First Inv Created'
union all select 7, 7, '2017-03-03 00:00:00.000', 6, 'Link ID'
union all select 8, 8, '2017-03-05 00:00:00.000', 7, 'Second In Created on top of Map Id'
union all select 9, 9, '2017-03-06 00:00:00.000', 8, 'Second Inv Created on top of Map Id'
--set input parameter
set #myInvId = 8
--init counters
set #father_counter = 1
set #children_counter = 1
--insert starting node
insert into #fathers select InvID,0 from #temp where OriginalInvID = #myInvId
insert into #children select OriginalInvID,0 from #temp where InvID = #myInvId
--loop on table
while (#father_counter + #children_counter) > 0
begin
--fetch father nodes
insert into #fathers select InvID, 1 from #temp where OriginalInvID in (select id from #fathers where status=0)
--update fathers' status
update #fathers set status = 2 where status = 0
update #fathers set status = 0 where status = 1
--fetch children nodes
insert into #children select OriginalInvID, 1 from #temp where InvID in (select id from #children where status=0)
--update children's status
update #children set status = 2 where status = 0
update #children set status = 0 where status = 1
--update counters
select #father_counter = count(*) from #fathers where status = 0
select #children_counter = count(*) from #children where status = 0
end
select #myInvId
union
select id from #fathers
union
select c.id from #children c inner join #temp t on c.id = t.InvID

How do I aggregate on more than one column within a PIVOT

I have two Column Users and NewUsers I need to sum those two as Quarterly so I am using pivot function so I have written query below....
code is
select [week],[years],pivoting.[1] as Q1 ,pivoting.[2] AS Q2,pivoting.[3] AS Q3,pivoting.[4] AS Q4,pivoting.[1] as N1,pivoting.[2] AS N2,pivoting.[3] AS N3,pivoting.[4] AS N4 into #addpivot from
(
select Week,years,Quarter,users,NewUsers from #pivottable
) as PivotData
pivot
(
sum(users) for Quarter in ([1],[2],[3],[4])
) as pivoting
pivot
(
sum(NewUsers) for Quarter in ([1],[2],[3],[4])
) as pivoting
but it showing error in second line Quarter invalid column name
Where I am going wrong not able understand please help me.......
I dint understand what do you mean by multiple values ...
Pivot is as simple as this ...
SELECT *
FROM table
PIVOT( SUM(NewUsers) FOR Quarter IN ([1],[2],[3],[4]) ) AS PVTTable
If I've read your data correctly, you need to unpivot your data and add a column to identify the values to pivot on before pivoting. I've called this 'Category' and used CROSS APPLY but you can also use CASE.
SELECT * INTO #PivotTable FROM (
VALUES
(1, 1, 1, 10, 12),
(1, 1, 1, 11, 13),
(1, 1, 2, 8, 10),
(1, 1, 2, 7, 11),
(1, 1, 3, 11, 14),
(1, 1, 3, 8, 15),
(1, 1, 4, 15, 10),
(1, 1, 4, 17, 11)
)A (Week,Years,Quarter,Users,NewUsers)
SELECT * FROM
(SELECT Week
,Years
,Category
,Value FROM #PivotTable
CROSS APPLY
(SELECT 'NewUsersQ'+CONVERT(VARCHAR(1),Quarter) Category, NewUsers Value
UNION ALL
SELECT 'UsersQ'+CONVERT(VARCHAR(1),Quarter) Category, Users Value
) A
) SRC
PIVOT (
SUM(Value) FOR Category IN
([UsersQ1], [NewUsersQ1], [UsersQ2], [NewUsersQ2], [UsersQ3], [NewUsersQ3], [UsersQ4], [NewUsersQ4])
)Pvt
Week Years UsersQ1 NewUsersQ1 UsersQ2 NewUsersQ2 UsersQ3 NewUsersQ3 UsersQ4 NewUsersQ4
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1 1 21 25 15 21 19 29 32 21
SELECT [week]
,[years]
,SUM(CASE WHEN Quarter = 1 THEN users ELSE 0 END) AS Q1
,SUM(CASE WHEN Quarter = 2 THEN users ELSE 0 END) AS Q2
,SUM(CASE WHEN Quarter = 3 THEN users ELSE 0 END) AS Q3
,SUM(CASE WHEN Quarter = 4 THEN users ELSE 0 END) AS Q4
,SUM(CASE WHEN Quarter = 1 THEN NewUsers ELSE 0 END) AS N1
,SUM(CASE WHEN Quarter = 2 THEN NewUsers ELSE 0 END) AS N2
,SUM(CASE WHEN Quarter = 3 THEN NewUsers ELSE 0 END) AS N3
,SUM(CASE WHEN Quarter = 4 THEN NewUsers ELSE 0 END) AS N4
FROM #pivottable
GROUP BY [week]
,[years]

SQL 2 statements creating a 3 statement, and joining the 2 together

This is my SQL statement:
SELECT repnr, DATEDIFF(day, MIN(start), MAX(start) +1) AS DaysTotal
FROM TBLstatus
WHERE status IN (1, 2, 3, 4, 8, 11, 20, 7, 23)
GROUP BY repnr HAVING COUNT(*) = 2 AND MAX(Start) > GETDATE()-30
Select repnr as repnr, CONVERT(float, SUM(DATEDIFF(day, start, slut))) as extern
From TBLstatus
where status IN (5, 15, 17)
group by repnr
The first will return this data:
repnr daystotal
1000 100
1001 90
1003 91
and the second statement:
repnr extern
900 100
901 102
1000 21
1003 23
What i want is that where the repnr (which is an ID) matches, i want to minus the to values so i would look like this:
repnr result
1000 79
1003 68
How do i do this for a MSSQL.
SELECT q1.repnr, q1.daystotal - q2.extern as [result]
FROM
(
SELECT repnr, DATEDIFF(day, MIN(start), MAX(start) +1) AS DaysTotal
FROM TBLstatus
WHERE status IN (1, 2, 3, 4, 8, 11, 20, 7, 23)
GROUP BY repnr HAVING COUNT(*) = 2 AND MAX(Start) > GETDATE()-30
)q1
INNER JOIN
(
Select repnr as repnr, CONVERT(float, SUM(DATEDIFF(day, start, slut))) as extern
From TBLstatus
where status IN (5, 15, 17)
group by repnr
)q2 ON q1.repnr = q2.repnr
Set your queries as subqueries and join on your key and you should be good to go.
select repnr, DaysTotal - extern as result from (SELECT repnr, DATEDIFF(day, MIN(start), MAX(start) +1) AS DaysTotal
FROM TBLstatus
WHERE status IN (1, 2, 3, 4, 8, 11, 20, 7, 23)
GROUP BY repnr HAVING COUNT(*) = 2 AND MAX(Start) > GETDATE()-30) a inner join (Select repnr as repnr, CONVERT(float, SUM(DATEDIFF(day, start, slut))) as extern
From TBLstatus
where status IN (5, 15, 17)
group by repnr) b on a.repnr = b.repnr
SELECT a.repnr, ABS(A.daystotal - b.extern) AS result
FROM(
SELECT repnr, DATEDIFF(day, MIN(start), MAX(start) +1) AS DaysTotal
FROM TBLstatus
WHERE status IN (1, 2, 3, 4, 8, 11, 20, 7, 23)
GROUP BY repnr HAVING COUNT(*) = 2 AND MAX(Start) > GETDATE()-30
)A
JOIN(
Select repnr as repnr, CONVERT(float, SUM(DATEDIFF(day, start, slut))) as extern
From TBLstatus
where status IN (5, 15, 17)
group by repnr
)B
ON A.repnr = b.repnr

Resources