Oracle sql using previous rows data in calculations - sql

I have a table T1 with 06 columns and want to get new two columns using a select query.
Here's T1 with two extra columns (STOCK, WAUC) that i want to get :
CREATE TABLE T1 (MOUVEMENT NUMBER(2), OPERATION VARCHAR2(5), ITEM VARCHAR2(5), INPUT_QTY NUMBER(6, 2), OUTPUT_QTY NUMBER(6, 2), INPUT_PRICE NUMBER(6, 2), STOCK NUMBER(6, 2), WAUC NUMBER(6, 2));
INSERT ALL
INTO T1 VALUES(1, 'I', 'A', 1500, 0, 5, 1500, 5)
INTO T1 VALUES(2, 'I', 'A', 700, 0, 6, 2200, 5.31)
INTO T1 VALUES(3, 'O', 'A', 0, 800, 0, 1400, 5.31)
INTO T1 VALUES(4, 'I', 'A', 1000, 0, 5, 2400, 5.18)
INTO T1 VALUES(5, 'O', 'A', 0, 500, 0, 1900, 5.18)
INTO T1 VALUES(6, 'I', 'A', 1000, 0, 7, 2900, 5.8 )
INTO T1 VALUES(7, 'I', 'A', 2000, 0, 7, 4900, 6.28)
INTO T1 VALUES(8, 'I', 'A', 5000, 0, 7, 5400, 6.34)
INTO T1 VALUES(9, 'O', 'A', 0, 1000, 0, 4400, 6.34)
INTO T1 VALUES(10, 'I','A', 1000, 0, 5, 5400, 6.09)
SELECT 1 FROM DUAL;
WAUC is like weighted average unit cost to valorise our stock.
In case first record : STOCK = INPUT and WAUC = INPUT_PRICE;
In case new INPUT operation : new WAUC should be : (last generated WAUC * last generated stock) + (current INPUT * current INPUT_PRICE)) / current generated STOCK.
Ex for 2nd row : WAUC = ((5 * 1500) + (700 * 6)) / 2200 = 5.31
In case new OUTPUT operation : WAUC should be last generated WAUC.
Ex for 3rd row : WAUC = last generated WAUC (5.31) of the same ITEM A.
Means, WAUC should be changed every new INPUT operation.
In my opinion, STOCK and WAUC should be generated on the fly, not as records,
besause otherwise, only one accidently wrong INPUT_PRICE, will cause wrong next WAUC(s) -> wrong next calculation(s) -> (wrong work).
how can I achieve this?
Thanks in advance.

Your logic is textbook example of need for model clause and can be rewritten to that clause almost as you verbosely specified (note the model clause is a beast, to learn more about it see here or here or here):
with t1 (mouvement, operation, item, input_qty, output_qty, input_price, stock_expected, wauc_expected) as (
select 1, 'I', 'A', 1500, 0, 5, 1500, 5 from dual union all
select 2, 'I', 'A', 700, 0, 6, 2200, 5.31 from dual union all
select 3, 'O', 'A', 0, 800, 0, 1400, 5.31 from dual union all
select 4, 'I', 'A', 1000, 0, 5, 2400, 5.18 from dual union all
select 5, 'O', 'A', 0, 500, 0, 1900, 5.18 from dual union all
select 6, 'I', 'A', 1000, 0, 7, 2900, 5.8 from dual union all
select 7, 'I', 'A', 2000, 0, 7, 4900, 6.28 from dual union all
select 8, 'I', 'A', 500, 0, 7, 5400, 6.34 from dual union all
select 9, 'O', 'A', 0, 1000, 0, 4400, 6.34 from dual union all
select 10, 'I','A', 1000, 0, 5, 5400, 6.09 from dual
)
select * from (
select t1.*, 0 as stock_actual, 0 as wauc_actual from t1
)
model
dimension by (row_number() over (order by mouvement) as rn)
measures (mouvement, operation, item, input_qty, output_qty, input_price, stock_expected, wauc_expected, stock_actual, wauc_actual)
rules (
stock_actual[any] = coalesce(stock_actual[cv(rn) - 1], 0) + case operation[cv(rn)]
when 'I' then input_qty[cv(rn)]
when 'O' then -output_qty[cv(rn)]
end,
wauc_actual[any] = case
when cv(rn) = 1
then input_price[cv(rn)]
when operation[cv(rn)] = 'I'
then trunc((wauc_actual[cv(rn) - 1] * stock_actual[cv(rn) - 1] + input_qty[cv(rn)] * input_price[cv(rn)]) / stock_actual[cv(rn)], 2)
when operation[cv(rn)] = 'O'
then wauc_actual[cv(rn) - 1]
end
)
order by mouvement
(I changed typo in operation=5000->500 for mouvement=8 and added truncation to 2 digits - both I guessed from your expected results.)
Db fiddle here.
Note that simple analytic functions are not sufficient for computation of wauc because they have access only to previous values of column of input dataset, not the values of column being computed by the function itself. For stock it would be possible using running totals of sum(input_qty) over (order by mouvement) - sum(output_qty) over (order by mouvement) but for wauc there is hardly any explicit formula.

Related

Averaging values and getting standard devs from database to build graph

Tricky to Explain so Ill shrink down the info to a minimum:
But first, I'll try and explain my ultimate goal, I want to take users who trialed a product and determine how that product affected a value as a percentage compared to their average baseline and then average all these percentages with stand devs.
I have database with the a table that has a user_id, a value, a date.
user_id
value
date
int
int
int in epoch miliseconds
I then have a second table which indicates when a trial began and ends for a user and the product they are using for said trial.
user_id
start_date
end_date
product id
int
int in epoch milisecs
int in epoch milisecs
int
What I want to do is gather all the user's trials for one product type, and for each user that participated get a baseline value and their percent change each day. Then take all these percentages and average them and get a standard deviation for each day.
One problem is date needs to convert to days since start_date so anything between the start date and the first 24 hrs will be lumped as day 0, next 24 as day 1, and so forth. So ill be averaging the percents of each day
Not every day was recorded for each user so some will have multiple missing days, so I cant need to mark each day as days from start
The start_date's are random between users
So the graph will look like this:
picture
I would prefer to do as much of it in sql as possible, but the rest will be in Golang.
I was thinking about grabbing each trial , and then each trial will have an array of results. so then I iterate over each trial and iteriate over the results for each trial picking day 0, day 1, day 2 and saving these in their own arrays which I will then average. Everything start getting super messy though
such as in semi pseudo code:
db.Query("select user_id, start_date from trials where product_id = $1", productId).Scan(&trial.UserId, &trial.StartDate)
//extract trials from rows
for _, trial := range trials {
// extract leadingAvgStart from StartDate
db.QueryRow("select AVG(value) from results where user_id = $1 date between $2 and $3", trial.UserId, leadingAvgStart, trial.StartDate)
// Now we have the baseline for the user
rows := db.Query("select value, date from results where product_id = $1", start)
//Now we extract the results and have and array
//Convert Dates to Dates from start Date
//...? It just start getting ugly and I believe there has to be a better way
}
How can I do most of the heavy lifting with sql?
create table users (id int PRIMARY KEY, name text);
create table products (id int PRIMARY KEY, name text);
create table values (
id int PRIMARY KEY
, user_id int REFERENCES users(id)
, value int
, date numeric
);
create table trials (
id int PRIMARY KEY
, user_id int REFERENCES users(id)
, start_date numeric
, end_date numeric
, product_id int REFERENCES products(id)
);
INSERT INTO users (id, name ) VALUES
(1,'John'),
(2,'Jane'),
(3,'Billy'),
(4,'Miranda');
INSERT INTO products (id, name ) VALUES
(1, 'pill A'),
(2, 'pill B'),
(3, 'pill C'),
(4, 'exercise bal'),
(5, 'diet plan');
INSERT INTO trials (id,user_id,start_date,end_date,product_id) VALUES
(1, 1, 1667896408000, 1668099442000, 1),
(2, 1, 1667896408000, 1668099442000, 2),
(3, 2, 1667576960000, 1668074401000, 3),
(4, 3, 1667896408000, 1668099442000, 1);
INSERT INTO values (id, user_id, value, date) VALUES
(38, 1, 7, 1668182428000),
(1, 1, 7, 1668099442000),
(2, 1, 8, 1668074401000),
(3, 1, 8, 1668012300000),
(4, 1, 6, 1668011197000),
(5, 1, 6, 1667978268000),
(6, 1, 9, 1667925002000),
(7, 1, 9, 1667896408000),
(8, 1, 4, 1667838601000),
(9, 1, 6, 1667803049000),
(10, 1, 7, 1667576960000),
(12, 1, 5, 1667546428000),
(13, 1, 8, 1667490149000),
(14, 2, 8, 1668182428000),
(15, 2, 7, 1668099442000),
(16, 2, 8, 1668074401000),
(17, 2, 9, 1668012300000),
(18, 2, 6, 1668011197000),
(19, 2, 6, 1667978268000),
(20, 2, 5, 1667925002000),
(21, 2, 9, 1667896408000),
(22, 2, 4, 1667803049000),
(23, 2, 4, 1667576960000),
(24, 2, 5, 1667546428000),
(25, 2, 9, 1667490149000),
(26, 3, 6, 1668182428000),
(27, 3, 7, 1668099442000),
(28, 3, 8, 1668074401000),
(29, 3, 9, 1668011197000),
(30, 3, 6, 1667978268000),
(31, 3, 9, 1667925002000),
(32, 3, 9, 1667896408000),
(33, 3, 8, 1667838601000),
(34, 3, 6, 1667803049000),
(35, 3, 4, 1667576960000),
(36, 3, 5, 1667546428000),
(37, 3, 6, 1667490149000);
Ok I figures it out, basically I do two inner join queries and treat those as tables and then inner join those, and use a group by to average
select
query1.product_uuid,
query1.days,
AVG(query1.value / query2.avg) as avg_percent
from
(
select
DATE_PART(
'day',
to_timestamp(
values
.date / 1000
):: date - trials.start_date
) as days,
trials.uuid as trial_uuid,
trials.product_uuid,
values
.value as value
from
values
as
values
inner join product_trials as trials ON
values
.user_id = trials.user_id
where
values
.source = 'Trued'
and
values
.use = 'true'
AND trials.start_date IS NOT NULL
AND trials.end_date IS NOT NULL
AND to_timestamp(
values
.date / 1000
):: date > trials.start_date
AND to_timestamp(
values
.date / 1000
):: date < trials.end_date
) as query1
inner join (
select
values
.user_id,
trials.uuid as trial_uuid,
AVG(value)
from
values
inner join product_trials as trials ON
values
.user_id = trials.user_id
where
source = 'Trued'
and use = true
AND trials.start_date IS NOT NULL
AND trials.end_date IS NOT NULL
AND to_timestamp(
values
.date / 1000
):: date < trials.start_date
AND DATE_PART(
'day',
to_timestamp(
values
.date / 1000
):: date - trials.start_date
) > -20
GROUP BY
values
.user_id,
trials.uuid
) as query2 ON query1.trial_uuid = query2.trial_uuid
where
query2.avg > 0
GROUP BY
query1.days,
query1.product_uuid
ORDER BY
query1.product_uuid,
query1.days

PostgreSQL: Return gaps and value mismatches between columns

Imagine the following data:
I am interested in returning the entries where there is a gap in the data for a particular student, where the category changes from one year to another, or both. So the output that I'm after is:
The reason why id 4 would not be returned is because there is actually no gap or difference between the values. Imagine the student only joined in year_2 and their last year was year_4. I'm only interested in returning gaps and/or scores different than the max score.
The code I'm using is:
with my_table (id, student, max_score, year_1, year_2, year_3, year_4, year_5)
as (values
(1, 'Alex', 7,null, 7, 7, null, 7),
(2, 'Bruno', 10, 10, 7, 10, 9, 10),
(3, 'Charlie', 7, 7, 5, null, 7, 7),
(4, 'Dan', 3,null, 3, 3, 3, null)
),
score_check as
(select *,
case
when (max_score <> year_1
or max_score <> year_2
or max_score <> year_3
or max_score <> year_4
or max_score <> year_5)
then false
else true
end as is_a_match
from my_table
)
select *
from score_check
where is_a_match is false
The issue with it is that it only returns me ids 2 and 3 - it is missing id 1 that has a gap (null value) in year_4.
How should I edit my code to return both gaps and values different from the max score?
Finding the gaps is the challenge here. To check for this, you can make a string from the values and a regular expression to find any digit-x-digit combinations, which you want to detect
dbfiddle.
with my_table (id, student, max_score, year_1, year_2, year_3, year_4, year_5)
as (values
(1, 'Alex', 7,null, 7, 7, null, 7),
(2, 'Bruno', 10, 10, 7, 10, 9, 10),
(3, 'Charlie', 7, 7, 5, null, 7, 7),
(4, 'Dan', 3,null, 3, 3, 3, null)
),
score_check as
(select *,
case when (
--Check if there is a gap by making a concatenating
--the values for all years, replacing nulls with an
--'x'. Use a regular expression to check if it matches
--a pattern looking like digit-character-digit
coalesce(year_1::character, 'x')||
coalesce(year_2::character, 'x')||
coalesce(year_3::character, 'x')||
coalesce(year_4::character, 'x')||
coalesce(year_5::character, 'x') ~ '\d+x\d+')
--Check if all scores are equal to the max_score
or
(
year_1 <> max_score or
year_2 <> max_score or
year_3 <> max_score or
year_4 <> max_score or
year_5 <> max_score
)
then false else true end is_a_match
from my_table
)
select *
from score_check
where is_a_match is false
You can generalize this to deal with more than just the five years for the dummies on the six-year plan:
with my_table (id, student, max_score, year_1, year_2, year_3, year_4, year_5) as (
values
(1, 'Alex', 7,null, 7, 7, null, 7), (2, 'Bruno', 10, 10, 7, 10, 9, 10),
(3, 'Charlie', 7, 7, 5, null, 7, 7), (4, 'Dan', 3,null, 3, 3, 3, null)
), unpivot1 as (
select to_jsonb(my_table) as j
from my_table
), unpivot2 as (
select (j->>'id')::int as id, j->>'max_score' as max_score, k, v,
replace(k, 'year_', '')::int as yearno
from unpivot1
cross join lateral jsonb_each_text(j) as e(k, v)
where k like 'year\_%'
), summary as (
select id,
string_agg(
case v = max_score
when true then 't'
when false then 'f'
else 'n'
end,
''
) as actual
from unpivot2
group by id
)
select t.*
from summary s
join my_table t on t.id = s.id
where trim(s.actual, 'n') ~ '[fn]'
;
db<>fiddle here

Find the correct matching record from multiple row using TSQL

I am shredding a XML file which contains different types of questions and their answers. I shredded it into a temp table and but got stuck for TickBox type of questions where the correct answer in different XML node and the options are in different nodes.
As shown in below screenshot, I shredded the XML into the table structure shown.
ID = 560 is TickBoxQuestion and the question you can see under column Value.
This TickBoxQuestion has 5 Multiple options from ID = 541 to 554 and the answer is under NodeName = Text. Note the NodeName = Value(1,2,3,4,5) are the OptionID's for these options which are under NodeName = Text.
The correct answer is listed in ID = 559 and Value = 3 which point to the OptionId under NodeName = Value = 3 so the answer is Value = 'Refinanced by a different adviser at a different firm'
Here is the sample data
CREATE TABLE dbo.Sample1
(
ID int,
ParentName varchar(1000),
ParentPosition int,
depth int,
NodeName varchar(1000),
Value varchar(1000),
FullPath varchar(1000),
XPath varchar(1000)
)
INSERT INTO Sample1 (ID, ParentName, ParentPosition, depth, NodeName, Value, FullPath, XPath)
SELECT 541, 'ListOption', 1, 7, 'Text', 'Term expired and loan paid off in full', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[1]/Text[1]' UNION ALL
SELECT 542, 'ListOption', 1, 7, 'Value', '1', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[1]/Value[1]' UNION ALL
SELECT 544, 'ListOption', 2, 7, 'Text', 'Refinanced by the same adviser', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[2]/Text[1]' UNION ALL
SELECT 545, 'ListOption', 2, 7, 'Value', '2', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[2]/Value[1]' UNION ALL
SELECT 547, 'ListOption', 3, 7, 'Text', 'Refinanced by a different adviser at a different firm', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[3]/Text[1]' UNION ALL
SELECT 548, 'ListOption', 3, 7, 'Value', '3', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[3]/Value[1]' UNION ALL
SELECT 550, 'ListOption', 4, 7, 'Text', 'Repaid early from own funds', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[4]/Text[1]' UNION ALL
SELECT 551, 'ListOption', 4, 7, 'Value', '4', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[4]/Value[1]' UNION ALL
SELECT 553, 'ListOption', 5, 7, 'Text', 'Still Active', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[5]/Text[1]' UNION ALL
SELECT 554, 'ListOption', 5, 7, 'Value', '5', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Options[1]/ListOption[5]/Value[1]' UNION ALL
SELECT 559, 'StringListAnswer', 1, 6, 'string', '3', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/StringListAnswer/string', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/StringListAnswer[1]/string[1]' UNION ALL
SELECT 560, 'TickBoxListQuestion', 1, 5, 'Text', 'What has happened to the loan or mortgage?', 'ArrayOfSection/Section/Elements/TickBoxListQuestion/Text', 'ArrayOfSection[1]/Section[1]/Elements[1]/TickBoxListQuestion[1]/Text[1]' UNION ALL
SELECT 757, 'ListOption', 1, 7, 'Text', 'A director of the Firm', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[1]/Text[1]' UNION ALL
SELECT 758, 'ListOption', 1, 7, 'Value', '1', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[1]/Value[1]' UNION ALL
SELECT 760, 'ListOption', 2, 7, 'Text', 'A manager of the Firm', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[2]/Text[1]' UNION ALL
SELECT 761, 'ListOption', 2, 7, 'Value', '2', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[2]/Value[1]' UNION ALL
SELECT 763, 'ListOption', 3, 7, 'Text', 'Employed/engaged by the Firm', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[3]/Text[1]' UNION ALL
SELECT 764, 'ListOption', 3, 7, 'Value', '3', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[3]/Value[1]' UNION ALL
SELECT 766, 'ListOption', 4, 7, 'Text', 'Directly or indirectly receiving a profit or payment or other benefit from the Firm', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[4]/Text[1]' UNION ALL
SELECT 767, 'ListOption', 4, 7, 'Value', '4', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[4]/Value[1]' UNION ALL
SELECT 769, 'ListOption', 5, 7, 'Text', 'The owner/a part-owner/a shareholder in the Firm or any related entity', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[5]/Text[1]' UNION ALL
SELECT 770, 'ListOption', 5, 7, 'Value', '5', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[5]/Value[1]' UNION ALL
SELECT 772, 'ListOption', 6, 7, 'Text', 'Acting as auditor/appointed actuary of the Firm or for any related entity', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[6]/Text[1]' UNION ALL
SELECT 773, 'ListOption', 6, 7, 'Value', '6', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[6]/Value[1]' UNION ALL
SELECT 775, 'ListOption', 7, 7, 'Text', 'No relation to the Firm', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[7]/Text[1]' UNION ALL
SELECT 776, 'ListOption', 7, 7, 'Value', '7', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Options/ListOption/Value', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Options[1]/ListOption[7]/Value[1]' UNION ALL
SELECT 781, 'StringListAnswer', 1, 6, 'string', '7', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/StringListAnswer/string', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/StringListAnswer[1]/string[1]' UNION ALL
SELECT 782, 'FirmInvolvementTickBoxListQuestion', 1, 5, 'Text', 'With respect to the Firm you are claiming for have you, your spouse or partner or a relative of either of you ever been any of the following?', 'ArrayOfSection/Section/Elements/FirmInvolvementTickBoxListQuestion/Text', 'ArrayOfSection[1]/Section[2]/Elements[1]/FirmInvolvementTickBoxListQuestion[1]/Text[1]'
I want to pivot and get the desired output as shown below
I am using SQL Server 2019.
Thanks

Using left or right join correctly in SQL [duplicate]

This question already has answers here:
SQL JOIN and different types of JOINs
(6 answers)
Closed 4 years ago.
I'm currently learning about left and right joins in class. It makes perfect sense when dealing with one-one or one-many tables but I can't figure out the many-many relationships.
I'm supposed to display a list of how much money a golfer raised each year even if its 0. So I should be showing 5 golfers for all 3 years for a total of 15 rows. No matter the combination of left, right or full I do, I only get the result of the TEventGolfers table.
INSERT INTO TEvents ( intEventID, strEventDate )
VALUES ( 1, '2015' )
,( 2, '2016' )
,( 3, '2017' )
INSERT INTO TGolfers( intGolferID, strFirstName, strLastName )
VALUES ( 1, 'Trevor', 'Duplin')
,( 2, 'Jay', 'Graue')
,( 3, 'Mary', 'Beimesch')
,( 4, 'Tony', 'Hardan')
,( 5, 'Iwana', 'Bucks')
INSERT INTO TEventGolfers ( intEventGolferID, intEventID, intGolferID )
VALUES (1, 1, 1)
,(2, 1, 2)
,(3, 1, 3)
,(4, 2, 4)
,(5, 2, 5)
,(6, 2, 1)
,(7, 3, 2)
,(8, 3, 3)
,(9, 3, 5)
INSERT INTO TEventGolferSponsors( intEventGolferSponsorID, intEventGolferID, intSponsorID, monPledgeAmount)
VALUES (1, 1, 1, 160.00)
,(2, 1, 1, 200.50)
,(3, 1, 2, 100.25)
,(4, 1, 3, 20.00)
,(5, 1, 4, 1500.00)
,(6, 1, 5, 220.20)
,(7, 1, 6, 120.00)
,(8, 1, 7, 2550.00)
,(9, 1, 1, 100.50)
,(10, 1, 2, 70.25)
,(11, 1, 3, 20.00)
,(12, 1, 4, 250.00)
,(13, 1, 5, 60.20)
,(14, 1, 6, 50.00)
,(15, 1, 7, 250.00)
-- Select Statements
SELECT TE.strEventDate, TG.strFirstName, ISNULL(SUM(TEGS.monPledgeAmount), 0) AS AmountRaised
FROM TGolfers AS TG
JOIN TEventGolfers AS TEG
ON TEG.intGolferID = TG.intGolferID
JOIN TEvents AS TE
ON TEG.intEventID = TE.intEventID
JOIN TEventGolferSponsors AS TEGS
ON TEGS.intEventGolferID = TEG.intEventGolferID
GROUP BY TG.strFirstName, TE.strEventDate
ORDER BY TE.strEventDate
This is more a CROSS JOIN problem then an outer join problem. First, you want to generate all combinations of golfers and years using CROSS JOIN. Then LEFT JOIN is then used to bring back results.
To see what I mean, run this query:
select e.strEventDate, g.strFirstName, g.strLastName
from tevents e cross join
tgolfers g;
You will see that the result set has all the rows you want -- but not all the columns. Next, you can add a LEFT JOIN to TEventGolfers to get the additional information in that table.
Because this is a homework problem, I'll let you complete the query.

Retrieving consecutive rows (and the counts) with the same values

I've got a table with almost 10 million views and would to run this query on the latest million or hundred thousand or so.
Here's a SQL fiddle with example data and input/output: http://sqlfiddle.com/#!9/340a41
Is this even possible?
CREATE TABLE object (`id` int, `name` varchar(7), `value` int);
INSERT INTO object (`id`, `name`, `value`)
VALUES
(1, 'a', 1),
(2, 'b', 2),
(3, 'c', 100),
(4, 'a', 1),
(5, 'b', 2),
(6, 'c', 200),
(7, 'a', 2),
(8, 'b', 2),
(9, 'c', 300),
(10, 'a', 2),
(11, 'b', 2),
(12, 'a', 2),
(13, 'b', 2),
(14, 'c', 400)
;
-- Want:
-- name, max(id), count(id)
-- 'a', 4, 2
-- 'b', 14, 5
-- 'a', 12, 3
If you want the latest and the id is implemented sequentially, then you can do this using limit or top. In SQL Server:
select top 100000 o.*
from object o
order by id desc;
In MySQL, you would use limit:
select o.*
from object o
order by id desc
limit 100000
select name, count(id) cnt, max(id) max_id, max(value) max_v
from
(select
top 1000000 -- MS SQL Server
id,name,value
from myTable
limit 1000000 --mySQL
order by id desc)
group by name
remove line which doesn't match your server.