Derive and Update Column Value based on Row Value SQL Server - sql

So I have a Request History table that I would like to flag its versions (version is based on end of cycle); I was able to mark the end of the cycle, but somehow I couldn't update the values of each associated with each cycle. Here is an example:
|history_id | Req_id | StatID | Time |EndCycleDate |
|-------------|---------|-------|---------- |-------------|
|1 | 1 |18 | 3/26/2017 | NULL |
|2 | 1 | 19 | 3/26/2017 | NULL |
|3 | 1 |20 | 3/30/2017 | NULL |
|4 |1 | 23 |3/30/2017 | NULL |
|5 | 1 |35 |3/30/2017 | 3/30/2017 |
|6 | 1 |33 |4/4/2017 | NULL |
|7 | 1 |34 |4/4/2017 | NULL |
|8 | 1 |39 |4/4/2017 | NULL |
|9 | 1 |35 |4/4/2017 | 4/4/2017 |
|10 | 1 |33 |4/5/2017 | NULL |
|11 | 1 |34 |4/6/2017 | NULL |
|12 | 1 |39 |4/6/2017 | NULL |
|13 | 1 |35 |4/7/2017 | 4/7/2017 |
|14 | 1 |33 |4/8/2017 | NULL |
|15 | 1 | 34 |4/8/2017 | NULL |
|16 | 2 |18 |3/28/2017 | NULL |
|17 | 2 |26 |3/28/2017 | NULL |
|18 | 2 |20 |3/30/2017 | NULL |
|19 | 2 |23 |3/30/2017 | NULL |
|20 | 2 |35 |3/30/2017 | 3/30/2017 |
|21 | 2 |33 |4/12/2017 | NULL |
|22 | 2 |34 |4/12/2017 | NULL |
|23 | 2 |38 |4/13/2017 | NULL |
Now what I would like to achieve is to derive a new column, namely VER, and update its value like the following:
|history_id | Req_id | StatID | Time |EndCycleDate | VER |
|-------------|---------|-------|---------- |-------------|------|
|1 | 1 |18 | 3/26/2017 | NULL | 1 |
|2 | 1 | 19 | 3/26/2017 | NULL | 1 |
|3 | 1 |20 | 3/30/2017 | NULL | 1 |
|4 |1 | 23 |3/30/2017 | NULL | 1 |
|5 | 1 |35 |3/30/2017 | 3/30/2017 | 1 |
|6 | 1 |33 |4/4/2017 | NULL | 2 |
|7 | 1 |34 |4/4/2017 | NULL | 2 |
|8 | 1 |39 |4/4/2017 | NULL | 2 |
|9 | 1 |35 |4/4/2017 | 4/4/2017 | 2 |
|10 | 1 |33 |4/5/2017 | NULL | 3 |
|11 | 1 |34 |4/6/2017 | NULL | 3 |
|12 | 1 |39 |4/6/2017 | NULL | 3 |
|13 | 1 |35 |4/7/2017 | 4/7/2017 | 3 |
|14 | 1 |33 |4/8/2017 | NULL | 4 |
|15 | 1 | 34 |4/8/2017 | NULL | 4 |
|16 | 2 |18 |3/28/2017 | NULL | 1 |
|17 | 2 |26 |3/28/2017 | NULL | 1 |
|18 | 2 |20 |3/30/2017 | NULL | 1 |
|19 | 2 |23 |3/30/2017 | NULL | 1 |
|20 | 2 |35 |3/30/2017 | 3/30/2017 | 1 |
|21 | 2 |33 |4/12/2017 | NULL | 2 |
|22 | 2 |34 |4/12/2017 | NULL | 2 |
|23 | 2 |38 |4/13/2017 | NULL | 2 |

One method that comes really close is a cumulative count:
select t.*,
count(endCycleDate) over (partition by req_id order by history_id) as ver
from t;
However, this doesn't get the value when the endCycle date is defined exactly right. And the value starts at 0. Most of these problems are fixed with a windowing clause:
select t.*,
(count(endCycleDate) over (partition by req_id
order by history_id
rows between unbounded preceding and 1 preceding) + 1
) as ver
from t;
But that misses the value on the first row first one. So, here is a method that actually works. It enumerates the values backward and then subtracts from the total to get the versions in ascending order:
select t.*,
(1 + count(*) over (partition by req_id) -
(count(endCycleDate) over (partition by req_id
order by history_id desc)
) as ver
from t;

Related

SUM with Windows Function BIGQUERY

I want to know the number of goals scored away and at home for each team in each season
season |home_goal |away_goal |team_home |team_away|
-----------------------------------------------------
1 | 1 |0 |France |Spain |
1 | 1 |2 |Italie |Spain |
1 | 0 |1 |Spain |Italie |
1 | 1 |3 |France |Italie |
1 | 1 |4 |Spain |Portugal |
1 | 3 |4 |Portugal |Italie |
2 | 1 |2 |France |Portugal |
2 | 1 |0 |Spain |Italie |
2 | 0 |1 |Spain |Portugal |
2 | 3 |2 |Italie |Spain |
2 | 0 |1 |France |Portugal |
... | ... |... |... |... |
I want this output
season |hg |ag |team |
-------------------------------------------
1 | 2 |0 |France |
1 | 1 |8 |Italie |
1 | 1 |2 |Spain |
1 | 3 |4 |Portugal |
2 | 1 |0 |France |
... | ... |... |... |
I don't have the expected result, I only have the goals scored at home...
WITH all_match AS (SELECT
season,
match.team_home AS ht,
match.home_goal AS hg
FROM
match
UNION ALL
SELECT
season,
match.team_away AS ta,
match.away_goal AS ag
FROM
match)
SELECT
season,
ht,
SUM(hg)
FROM
all_match
group by 1,2
Use below approach
select * from (
select season, 'home' location, team_home as team, home_goal as goal
from your_table
union all
select season, 'away' location, team_away as team, away_goal as goal
from your_table
)
pivot (sum(goal) for location in ('home', 'away'))
if applied to sample data in your question - output is

SQL Identify Unique User from multiple columns

Is there anyway to create a unique identifier column (user) for a user so that if Email, User_ID or Subscription_ID is a match between any of the rows then I will be able to group by and aggregate by this unique identifier later? The unique identifier doesn't have to be incrementing but I thought that could be a way of implementing it.
Data which could call subscriptions table:
|Email |User_ID | Subscription_ID |
|--------------|-----------|--------------------|
|12#gmail.com |20 | 56 |
|12#gmail.com |30 | 86 |
|13#gmail.com |20 | 96 |
|14#gmail.com |22 | 96 |
|15#gmail.com |80 | 12 |
Desired Result:
|Email |User_ID | Subscription_ID | User |
|--------------|-----------|--------------------|------|
|12#gmail.com |20 | 56 | 1 |
|12#gmail.com |30 | 86 | 1 |
|13#gmail.com |20 | 96 | 1 |
|14#gmail.com |22 | 96 | 1 |
|15#gmail.com |80 | 12 | 2 |

How can I get row index in sql

Table Contents are:
|Emp_ID | Name |
|-------|-------|
|1 | xyz |
|23 | pqq |
|22 | wdd |
|12 | fdv |
Here I want the row index where Emp_ID is greater than 15.
Result should return 2 and 3

Stored Procedure IF Exist Update Else Insert, if match

I got a lot of help form different articles, for which i thank you a lot.
But, right now i have a case were i need your support namely related with an SQL procedure which not only is checking if data exists (for update or insert it, but i have to match it with other 2 tables to check if data is matching then insert the same row with different values for some columns on a separate table).
I hope to be more explicit, so the example below I hope to help
Main row data : db.Table1
|rowID|PurchaseDate|ProducID | ProductName | CustomerID | Qty | UnitType|
|row1 |09.09.2018 |206 | Prod1 | 1 | 10 | bl. |
|row2 |09.09.2018 |207 | Prod2 | 2 | 15 | bl. |
|row3 |12.09.2018 |203 | Prod5 | 5 | 5 | lk. |
|row4 |15.09.2018 |207 | Prod2 | 6 | 10 | lk. |
|row5 |20.09.2018 |207 | Prod2 | 8 | 3 | Pk. |
|row6 |20.09.2018 |203 | Prod5 | 8 | 6 | Pk. |
|row7 |20.09.2018 |205 | Prod0 | 2 | 5 | J. |
to match with: db.Table2
|CustomerID| CustomerName|
|1 | Customer1 |
|2 | Customer2 |
|3 | Customer3 |
|4 | Customer4 |
|5 | Customer5 |
to match with: db.Table3
|ProducID| ProductName| SubProdNAME| |
|205 | Prod0 | Prod101 |
|205 | Prod0 | Prod202 |
|204 | Prod01 | Prod1001 |
|204 | Prod01 | Prod2002 |
to final table: db.TableFIN
|rowID| PurchaseDate|ProducID|ProductName|CustomerID|Qty|UnitType |Stage|
|row1 | 09.09.2018 | 206 | Prod1 | 1 |10 | bl. | DONE|
|row1 | 09.09.2018 | 206 | Prod1 | 1 |10 | bl. | NONE|
|row2 | 09.09.2018 | 207 | Prod2 | 2 |15 | bl. | DONE|
|row2 | 09.09.2018 | 207 | Prod2 | 2 |15 | bl. | NONE|
|row3 | 12.09.2018 | 203 | Prod5 | 5 |5 | lk. | DONE|
|row3 | 12.09.2018 | 203 | Prod5 | 5 |5 | lk. | NONE|
|row4 | 15.09.2018 | 207 | Prod2 | 6 |10 | lk. | DONE|
|row4 | 15.09.2018 | 207 | Prod2 | 6 |0 | lk. | NONE|
|row5 | 20.09.2018 | 207 | Prod2 | 8 |3 | Pk. | DONE|
|row5 | 20.09.2018 | 207 | Prod2 | 8 |0 | Pk. | NONE|
|row6 | 20.09.2018 | 203 | Prod5 | 8 |6 | Pk. | DONE|
|row6 | 20.09.2018 | 203 | Prod5 | 8 |0 | Pk. | NONE|
|row7 | 20.09.2018 | 205 | Prod101 | 3 |5 | bundle| DONE|
|row7 | 20.09.2018 | 205 | Prod101 | 3 |5 | bundle| NONE|
|row7 | 20.09.2018 | 205 | Prod202 | 3 |5 | bundle| DONE|
|row7 | 20.09.2018 | 205 | Prod202 | 3 |5 | bundle| NONE|
So, basically what i need is to insert data by row depending on Stage, one row with stage DONE and second with NONE - plus, in case the consumerID it matches then Qty value it's equal in both cases, otherwise for NONE value = 0 and for DONE the original value.
FOR ProducID if it matches the product, then we have to insert 4 rows. as on above table. Again matching consumerID & Prod updating/inserting stage/values.
YOur support, is highly appreciated.
Thank you in advance!

Change in foreign table affect the previous report

Actually I am stuck in one issue. I have a table:
tbl_color
+------------+
|id | name |
|---|--------|
|1 | Red |
|---|--------|
|2 | Blue |
|---|--------|
|3 | Black |
+------------+
tbl_clothes
+----------------+
|id | name |
| 1 | Pant |
| 2 | Shirt |
| 3 | T-shirt |
+----------------+
tb_sales
+---------------------------------------+
|id | id_cloth | id_color | sales_date |
|---|----------|-----------|------------|
|1 | 1 | 1 | 2016/1/1 |
|---|----------|-----------|------------|
|2 | 1 | 3 | 2016/1/1 |
|---|----------|-----------|------------|
|3 | 1 | 1 | 2016/2/2 |
+---------------------------------------+
So when I change one row of tbl_color to
tbl_color
+---------------------------+
|id | name | modified_on |
|----|--------|-------------|
|1 | Orange | 2016/3/2 |
|----|--------|-------------|
|2 | Blue | 2016/1/2 |
|----|--------|-------------|
|3 | Black | 2016/1/2 |
+---------------------------+
So when I want to get report of sales on 2016/1/1
SELECT * from table tb_sales
JOIN tbl_clothes ON tbl_clothes.id = tbl_sales.id_cloth
JOIN tbl_sales ON tbl_color.id = tbl_sales.id_color
where sales_date = '2016/1/1'
I get the report that have been modified no the original sales
How can I handle this issue?