Reformat existing table from paired columns into rows - sql-server

For example I have a table with 5 rows and 7 columns, I wish to move the last two columns into the previous two columns. New format of table would now be 10 rows and 5 columns
Present Table format
+-----+------------+----------+------------+---------------+------------+---------------+
| id | VisitDate | fkFamily | child1.DOB | child1.Gender | child2.DOB | child2.Gender |
+-----+------------+----------+------------+---------------+------------+---------------+
| 78 | 19/04/2010 | 277 | 14/03/2009 | 0 | NULL | NULL |
| 79 | 20/04/2010 | 289 | 12/08/2007 | 0 | NULL | NULL |
| 107 | 20/04/2010 | 191 | NULL | NULL | NULL | NULL |
| 108 | 20/04/2010 | 259 | NULL | NULL | 31/03/2010 | 1 |
| 109 | 20/04/2010 | 126 | NULL | NULL | NULL | NULL |
+-----+------------+----------+------------+---------------+------------+---------------+
New table format
+-----+------------+----------+------------+----------------------+
| id | VisitDate | fkFamily | child.DOB | child.Gender |
+-----+------------+----------+------------+----------------------+
| 78 | 19/04/2010 | 277 | 14/03/2009 | 0 |
| 79 | 20/04/2010 | 289 | 12/08/2007 | 0 |
| 107 | 20/04/2010 | 191 | NULL | NULL |
| 108 | 20/04/2010 | 259 | NULL | NULL |
| 109 | 20/04/2010 | 126 | NULL | NULL |
| 78 | 19/04/2010 | 277 | NULL | NULL |
| 79 | 20/04/2010 | 289 | NULL | NULL |
| 107 | 20/04/2010 | 191 | NULL | NULL |
| 108 | 20/04/2010 | 259 | 31/03/2010 | 1 |
| 109 | 20/04/2010 | 126 | NULL | NULL |
+-----+------------+----------+------------+----------------------+

You can get the final result by unpivoting the columns Child1_DOB, Child1_Gender, etc. Starting in SQL Server 2005, the unpivot function was made available but for your case I'd actually use CROSS APPLY so you can unpivot the Child1, and Child2 values in pairs.
The syntax would be:
select
t.id,
t.visitdate,
t.fkFamily,
c.child_DOB,
c.child_Gender
from yourtable t
cross apply
(
select child1_DOB, child1_Gender union all
select child2_DOB, child2_Gender
) c (child_DOB, child_Gender);
See SQL Fiddle with Demo
Then you could also include an identifier for each of the values so you know if it belonged to child one or two:
select
t.id,
t.visitdate,
t.fkFamily,
c.child,
c.child_DOB,
c.child_Gender
from yourtable t
cross apply
(
select 'Child1', child1_DOB, child1_Gender union all
select 'Child2', child2_DOB, child2_Gender
) c (child, child_DOB, child_Gender)
See SQL Fiddle with Demo. These give a result similar to:
| ID | VISITDATE | FKFAMILY | CHILD_DOB | CHILD_GENDER |
|-----|------------|----------|------------|--------------|
| 78 | 19/04/2010 | 277 | 14/03/2009 | 0 |
| 78 | 19/04/2010 | 277 | (null) | (null) |
| 79 | 20/04/2010 | 289 | 12/08/2007 | 0 |
| 79 | 20/04/2010 | 289 | (null) | (null) |
| 107 | 20/04/2010 | 191 | (null) | (null) |
| 107 | 20/04/2010 | 191 | (null) | (null) |
| 108 | 20/04/2010 | 259 | (null) | (null) |
| 108 | 20/04/2010 | 259 | 31/03/2010 | 1 |
| 109 | 20/04/2010 | 126 | (null) | (null) |
| 109 | 20/04/2010 | 126 | (null) | (null) |

You could reformat the table into something like this by using UNION:-
SELECT * FROM (
SELECT id, VisitDate, fkFamily, child1_DOB as child_DOB, child1_Gender as child_Gender
FROM yourtable
UNION
SELECT id, VisitDate, fkFamily, child2_DOB, child2_Gender
FROM yourtable) as temp
FIDDLE
You could use SELECT INTO if you wanted to create a new table from the results, for example:-
SELECT * INTO yournewtable FROM (
SELECT id, VisitDate, fkFamily, child1_DOB as child_DOB, child1_Gender as child_Gender
FROM yourtable
UNION
SELECT id, VisitDate, fkFamily, child2_DOB, child2_Gender
FROM yourtable) as temp

Related

Pivoting a table with multiple columns in SQL

My goal here is to take a list of two corresponding store numbers and provide an output similar to:
Ultimate goal: produce a list of closest stores by travel time and distance based on source data of 2 rows per zip9 where each row is the travel time in distance, and in time, to a store in question.
The result is that each zip code has 2 stores to choose from, and the requirement is being able to return one row with both options.
+-----------+---------------+---------------------+-------------------+-------------------------+
| zip | Shortest_time | Shortest_time_store | Shortest_distance | Shortest_distance_store |
+-----------+---------------+---------------------+-------------------+-------------------------+
| 70011134 | 38.7035 | 75 | 21.3124 | 115 |
| 70011186 | 38.4841 | 75 | 21.4144 | 115 |
| 70011207 | 39.1567 | 75 | 21.1826 | 115 |
| 100013232 | 22.976 | 145 | 9.5031 | 115 |
| 112075140 | 21.888 | 145 | 7.3705 | 115 |
+-----------+---------------+---------------------+-------------------+-------------------------+
Original dataset
+---------------+--------------------------+-----------------------+------------------+
| CORRECTED_ZIP | SourceOrganizationNumber | Travel Time (Minutes) | Distance (Miles) |
+---------------+--------------------------+-----------------------+------------------+
| 70011134 | 75 | 38.7035 | 26.8628 |
| 70011134 | 115 | 39.3969 | 21.3124 |
| 70011186 | 75 | 38.4841 | 26.7609 |
| 70011186 | 115 | 39.6389 | 21.4144 |
| 70011207 | 75 | 39.1567 | 31.2771 |
| 70011207 | 115 | 39.188 | 21.1826 |
| 100013232 | 115 | 28.6561 | 9.50311 |
| 100013232 | 145 | 22.976 | 10.0307 |
| 112075140 | 115 | 36.1803 | 7.37053 |
| 112075140 | 145 | 21.888 | 9.50123 |
+---------------+--------------------------+-----------------------+------------------+
Dataset after I've modified it with this query:
SELECT TOP 1000 [corrected_zip]
, TRY_CONVERT( DECIMAL(18, 4), ROUND([Travel Time (Minutes)], 4)) AS [Unit of Measurement]
, [SourceOrganizationNumber]
, 'Time' AS [Type]
FROM [db].[dbo].[my_table_A] [tt]
WHERE [tt].[CORRECTED_ZIP] IN('070011134', '070011186', '070011207', '112075140', '100013232')
AND [Travel Time (Minutes)] IN
(
SELECT MIN([Travel Time (Minutes)])
FROM [db].[dbo].[my_table_A]
WHERE [CORRECTED_ZIP] = [tt].[CORRECTED_ZIP]
GROUP BY [CORRECTED_ZIP]
)
UNION ALL
SELECT TOP 1000 [corrected_zip]
, TRY_CONVERT( DECIMAL(18, 4), ROUND([Distance (Miles)], 4))
, [SourceOrganizationNumber]
, 'Distance'
FROM [db].[dbo].[my_table_A] [tt]
WHERE [tt].[CORRECTED_ZIP] IN('070011134', '070011186', '070011207', '112075140', '100013232')
AND [Distance (Miles)] IN
(
SELECT MIN([Distance (Miles)])
FROM [db].[dbo].[my_table_A]
WHERE [CORRECTED_ZIP] = [tt].[CORRECTED_ZIP]
GROUP BY [CORRECTED_ZIP]
)
ORDER BY [CORRECTED_ZIP];
+---------------+---------------------+--------------------------+----------+
| corrected_zip | Unit of Measurement | SourceOrganizationNumber | Type |
+---------------+---------------------+--------------------------+----------+
| 70011134 | 38.7035 | 75 | Time |
| 70011134 | 21.3124 | 115 | Distance |
| 70011186 | 21.4144 | 115 | Distance |
| 70011186 | 38.4841 | 75 | Time |
| 70011207 | 39.1567 | 75 | Time |
| 70011207 | 21.1826 | 115 | Distance |
| 100013232 | 9.5031 | 115 | Distance |
| 100013232 | 22.976 | 145 | Time |
| 112075140 | 21.888 | 145 | Time |
| 112075140 | 7.3705 | 115 | Distance |
+---------------+---------------------+--------------------------+----------+
Data after I attempted to pivot it
+---------------+--------------------------+----------+---------+
| corrected_zip | SourceOrganizationNumber | Distance | Time |
+---------------+--------------------------+----------+---------+
| 070011134 | 115 | 21.3124 | NULL |
| 070011134 | 75 | NULL | 38.7035 |
| 070011186 | 115 | 21.4144 | NULL |
| 070011186 | 75 | NULL | 38.4841 |
| 070011207 | 115 | 21.1826 | NULL |
| 070011207 | 75 | NULL | 39.1567 |
| 100013232 | 115 | 9.5031 | NULL |
| 100013232 | 145 | NULL | 22.9760 |
| 112075140 | 115 | 7.3705 | NULL |
| 112075140 | 145 | NULL | 21.8880 |
+---------------+--------------------------+----------+---------+
It seems like my issue is picking the correct store ID as opposed to grouping by store ID?
You can use row_number() twice in a subquery(once to rank by time, another by distance), and then do conditional aggregation in the outer query:
select
corrected_zip,
min(travel_time) shortest_time,
min(case when rnt = 1 then source_organization_number end) shortest_time_store,
min(distance) shortest_distance,
min(case when rnd = 1 then source_organization_number end) shortest_distance_store
from (
select
t.*,
row_number() over(partition by corrected_zip order by travel_time) rnt,
row_number() over(partition by corrected_zip order by distance) rnd
from mytable t
) t
group by corrected_zip

Cumulative Count of NULL restarting at NOT NULL

I would like to add a column indicating the number invites a person received before they accepted by incrementally counting the number of null columns before a non-null while partitioning over the PERSON_ID and ordering by the INVITED_DATE.
My table has the following format:
| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE |
| 12345 | 567 | 12-01-18 | NULL |
| 12346 | 567 | 12-02-18 | NULL |
| 12347 | 567 | 12-03-18 | NULL |
| 12348 | 567 | 12-04-18 | 12-04-18 |
| 12349 | 567 | 12-05-18 | NULL |
| 12350 | 568 | 12-01-18 | NULL |
| 12351 | 568 | 12-02-18 | 12-02-18 |
The output should ideally look like the following:
| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE | INVITES_BEFORE_ACCEPT |
| 12345 | 567 | 12-01-18 | NULL | 1 |
| 12346 | 567 | 12-02-18 | NULL | 2 |
| 12347 | 567 | 12-03-18 | NULL | 3 |
| 12348 | 567 | 12-04-18 | 12-04-18 | 0 |
| 12349 | 567 | 12-05-18 | NULL | 1 |
| 12350 | 568 | 12-01-18 | NULL | 1 |
| 12351 | 568 | 12-02-18 | 12-02-18 | 0 |
So far I've tried a number iterations of ROW NUMBER with OVER and PARTITION but I've found it will need to be an OUTER APPLY. The following OUTER APPLY counts over the data but doesn't restart the count with a successful accept.
SELECT t.* , invites.INVITES_BEFORE_ACCEPT
FROM table t
OUTER APPLY (
SELECT COUNT(*) INVITES_BEFORE_ACCEPT
FROM table t2
WHERE t.PERSON_ID = t2.PERSON_ID and t.INVITED_DATE < t2.ACCEPTED_DATE
) invites
One way would be
WITH t
AS (SELECT *,
COUNT(ACCEPTED_DATE)
OVER (
PARTITION BY PERSON_ID
ORDER BY INVITED_DATE) AS Grp
FROM [table])
SELECT *,
SUM(CASE
WHEN ACCEPTED_DATE IS NULL
THEN 1
ELSE 0
END)
OVER (
PARTITION BY PERSON_ID, Grp
ORDER BY INVITED_DATE) AS INVITES_BEFORE_ACCEPT
FROM t
Demo

Trying to create a parent-child hierarchy in sql server

I have a data set that is sorted by account key. when coming to certain rows which have NULL as group key, it should add current account key as a parent key for all above rows which have NULL as parentkey. So when coming to the next row with null as group key, you would set the current account key as parent key for all rows above that have parent key like null.
I have tried to copy a dataset below as mark down table but as you see I can't say I succeeded very well, but I hope some of you can help with the t-sql syntax to create a parent-child hierarchy of this
| AccountKey | ParentKey | GroupKey | AccountNumber | Cat | LineName | LineId |
|------------|-----------|----------|---------------|----------|------------------------------|--------------------------------------|
| 1 | NULL | 7 | 3040 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 2 | NULL | 7 | 3041 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 3 | NULL | 7 | 3081 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 4 | NULL | 7 | 3082 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 5 | NULL | 7 | 3083 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 6 | NULL | 7 | 3085 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 7 | NULL | 7 | 3086 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 8 | NULL | 7 | 3087 | Account | Salg fisk | C6BCDFB2-1AAC-4D05-94F1-879CDC615D76 |
| 9 | NULL | 2 | 3000 | Account | Salg annet | 26AC86B2-0667-463E-B994-11A5C6D519A6 |
| 10 | NULL | 2 | 3010 | Account | Salg annet | 26AC86B2-0667-463E-B994-11A5C6D519A6 |
| 11 | NULL | 2 | 3020 | Account | Salg annet | 26AC86B2-0667-463E-B994-11A5C6D519A6 |
| 12 | NULL | 2 | 3030 | Account | Salg annet | 26AC86B2-0667-463E-B994-11A5C6D519A6 |
| 41 | NULL | 11 | 3050 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 42 | NULL | 11 | 3600 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 43 | NULL | 11 | 3601 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 44 | NULL | 11 | 3610 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 45 | NULL | 11 | 3615 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 46 | NULL | 11 | 3690 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 47 | NULL | 11 | 3691 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 48 | NULL | 11 | 3701 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 49 | NULL | 11 | 3705 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 50 | NULL | 11 | 3720 | Account | Andre driftsinntekter | 65FFB620-AE42-4BE5-A6E7-BF3339AA04DF |
| 67 | NULL | NULL | NULL | SubTotal | Sum inntekter | NULL |
| 68 | NULL | 13 | 4120 | Account | Innkjøp smolt/settefisk/rogn | F9EE1CE4-22C7-400B-BC9D-E2D3214A5113 |
| 69 | NULL | 10 | 4010 | Account | Vareforbruk fôr | 04E63B6D-CA54-423D-8A44-A4ED99861975 |
| 70 | NULL | 10 | 4901 | Account | Vareforbruk fôr | 04E63B6D-CA54-423D-8A44-A4ED99861975 |
| 71 | NULL | 3 | 4000 | Account | Andre varekostnader | DB7FABAB-7ABA-4B9A-9720-1B538D99B3C8 |
| 72 | NULL | 3 | 4020 | Account | Andre varekostnader | DB7FABAB-7ABA-4B9A-9720-1B538D99B3C8 |
| 73 | NULL | 3 | 4030 | Account | Andre varekostnader | DB7FABAB-7ABA-4B9A-9720-1B538D99B3C8 |
| 133 | NULL | 8 | 4925 | Account | Beholdningsendring fisk | A8BA6F19-A792-44A1-AA21-8F79DB24D224 |
| 134 | NULL | NULL | NULL | SubTotal | Sum varekostnader | NULL |
| 135 | NULL | 12 | 5000 | Account | Lønn og sosiale kostnader | 5C475EDE-3731-4D39-B11A-C8EE72213FF6 |
| 136 | NULL | 12 | 5001 | Account | Lønn og sosiale kostnader | 5C475EDE-3731-4D39-B11A-C8EE72213FF6 |
| 137 | NULL | 12 | 5005 | Account | Lønn og sosiale kostnader | 5C475EDE-3731-4D39-B11A-C8EE72213FF6 |
| 138 | NULL | 12 | 5009 | Account | Lønn og sosiale kostnader | 5C475EDE-3731-4D39-B11A-C8EE72213FF6 |
| 263 | NULL | NULL | NULL | SubTotal | Sum lønnskostnadern | NULL |
| 462 | NULL | NULL | NULL | SubTotal | RESULTAT ETTER SKATT | NULL
If I understood your question you could use:
SELECT Accountkey, ParentKey,GroupKey,AccountNumber, NEW_PARID
FROM (
SELECT Accountkey, ParentKey,GroupKey,AccountNumber, AccountKey AS NEW_PARID, LAG(ACCOUNTKEY) OVER (ORDER BY Accountkey) AS PREC
FROM MYT
WHERE GroupKey IS NULL
UNION ALL
SELECT A.Accountkey, A.ParentKey,A.GroupKey,A.AccountNumber, B.Accountkey AS NEW_PARID, B.PREC
FROM MYT A
INNER JOIN ( SELECT Accountkey, ParentKey,GroupKey,AccountNumber, AccountKey AS NEW_PARID, LAG(ACCOUNTKEY) OVER (ORDER BY Accountkey) AS PREC
FROM MYT
WHERE GroupKey IS NULL) B ON A.Accountkey < B.Accountkey AND (B.PREC IS NULL OR B.PREC<A.accountKey)
WHERE A.GroupKey IS NOT NULL
AND B.GroupKey IS NULL
) X ORDER BY ACCOUNTKEY
You can write it in this way too (it's the same query):
WITH X AS (SELECT Accountkey, ParentKey,GroupKey,AccountNumber, AccountKey AS NEW_PARID, LAG(ACCOUNTKEY) OVER (ORDER BY Accountkey) AS PREC
FROM MYT
WHERE GroupKey IS NULL)
SELECT X.*
FROM X
UNION ALL
SELECT A.Accountkey, A.ParentKey,A.GroupKey,A.AccountNumber, X.Accountkey AS NEW_PARID, X.PREC
FROM MYT A
INNER JOIN X ON A.Accountkey < X.Accountkey AND (X.PREC IS NULL OR X.PREC<A.accountKey)
WHERE A.GroupKey IS NOT NULL
Output (MYT is the name of the table, the new parentid column is NEW_PARID):
+------------+-----------+----------+---------------+-----------+
| Accountkey | ParentKey | GroupKey | AccountNumber | NEW_PARID |
+------------+-----------+----------+---------------+-----------+
| 1 | NULL | 7 | 3040 | 67 |
| 2 | NULL | 7 | 3041 | 67 |
| 3 | NULL | 7 | 3081 | 67 |
| 4 | NULL | 7 | 3082 | 67 |
| 5 | NULL | 7 | 3083 | 67 |
| 6 | NULL | 7 | 3085 | 67 |
| 7 | NULL | 7 | 3086 | 67 |
| 8 | NULL | 7 | 3087 | 67 |
| 9 | NULL | 2 | 3000 | 67 |
| 10 | NULL | 2 | 3010 | 67 |
| 11 | NULL | 2 | 3020 | 67 |
| 12 | NULL | 2 | 3030 | 67 |
| 41 | NULL | 11 | 3050 | 67 |
| 42 | NULL | 11 | 3600 | 67 |
| 43 | NULL | 11 | 3601 | 67 |
| 44 | NULL | 11 | 3610 | 67 |
| 45 | NULL | 11 | 3615 | 67 |
| 46 | NULL | 11 | 3690 | 67 |
| 47 | NULL | 11 | 3691 | 67 |
| 48 | NULL | 11 | 3701 | 67 |
| 49 | NULL | 11 | 3705 | 67 |
| 50 | NULL | 11 | 3720 | 67 |
| 67 | NULL | NULL | NULL | 67 |
| 68 | NULL | 13 | 4120 | 134 |
| 69 | NULL | 10 | 4010 | 134 |
| 70 | NULL | 10 | 4901 | 134 |
| 71 | NULL | 3 | 4000 | 134 |
| 72 | NULL | 3 | 4020 | 134 |
| 73 | NULL | 3 | 4030 | 134 |
| 133 | NULL | 8 | 4925 | 134 |
| 134 | NULL | NULL | NULL | 134 |
| 135 | NULL | 12 | 5000 | 263 |
| 136 | NULL | 12 | 5001 | 263 |
| 137 | NULL | 12 | 5005 | 263 |
| 138 | NULL | 12 | 5009 | 263 |
| 263 | NULL | NULL | NULL | 263 |
| 462 | NULL | NULL | NULL | 462 |
+------------+-----------+----------+---------------+-----------+
Updated 20171221 - for MSSQL 2008
You can try this (but pay attention for performance if you have a large dataset):
SELECT A.ACCOUNTKEY
, A.PARENTKEY
, (SELECT MIN(B.ACCOUNTKEY) FROM MYT B WHERE B.GROUPKEY IS NULL AND A.ACCOUNTKEY<=B.ACCOUNTKEY) AS NEW_PARID
FROM MYT A
/* WHERE A.GROUPKEY IS NOT NULL*/
This is the code I need to rewrite to work on SQL Server 2008
SELECT AccountKey,
LineName,
AccountName,
GroupKey,
AccountNumber,
ParentAccountKey
INTO tempAccount
FROM
(
SELECT AccountKey,
LineName,
AccountName,
GroupKey,
AccountNumber,
AccountKey AS ParentAccountKey,
LAG(AccountKey) OVER(ORDER BY AccountKey) AS PREC
FROM tempTable2
WHERE GroupKey IS NULL
UNION ALL
SELECT A.AccountKey,
A.LineName,
A.AccountName,
A.GroupKey,
A.AccountNumber,
B.AccountKey AS ParentAccountKey,
B.PREC
FROM tempTable2 A
INNER JOIN
(
SELECT AccountKey,
LineName,
AccountName,
GroupKey,
AccountNumber,
AccountKey AS ParentAccountKey,
LAG(AccountKey) OVER(ORDER BY AccountKey) AS PREC
FROM tempTable2
WHERE GroupKey IS NULL
) B ON A.AccountKey < B.AccountKey
AND (B.PREC IS NULL
OR B.PREC < A.AccountKey)
WHERE A.GroupKey IS NOT NULL
AND B.GroupKey IS NULL
) X
ORDER BY AccountKey;

SQL Server 2008 R2 running sum

I have a table like below.
row_no and product are PK.
+--------+---------+-------+-----+---------------+---------+
| row_no | Product | value | qoh | prev_week_qty | cum_qty |
+--------+---------+-------+-----+---------------+---------+
| 1 | pr:1 | 101 | 101 | NULL | NULL |
| 2 | pr:1 | 201 | 101 | NULL | 100 |
| 3 | pr:1 | 101 | 101 | NULL | NULL |
| 4 | pr:1 | 101 | 101 | NULL | NULL |
| 5 | pr:1 | 183 | 101 | NULL | -18 |
| 6 | pr:1 | 101 | 101 | NULL | NULL |
| 7 | pr:1 | 101 | 101 | NULL | NULL |
| 8 | pr:1 | 149 | 101 | NULL | -34 |
| 9 | pr:1 | 131 | 101 | NULL | -18 |
| 10 | pr:1 | 101 | 101 | NULL | NULL |
| 11 | pr:1 | 113 | 101 | NULL | -18 |
| 12 | pr:1 | 101 | 101 | NULL | NUll |
| 13 | pr:1 | 101 | 101 | NULL | NUll |
| 14 | pr:1 | 101 | 101 | NULL | NUll |
| 17 | pr:1 | 101 | 101 | NULL | NULL |
+--------+---------+-------+-----+---------------+---------+
Is there any way to implement this without usig cusrsor?
Logic: Value = qoh + cum_qty + prev_week_qty
For ex:
For row_no=1, value = qoh+prev_week_qty+cum_qty.
For row_no=2, qoh = (row_no = 1.value), then qoh+ prev_week_qty+cum_qty
For row_no=3, qoh = (row_no = 2.value), then qoh+ prev_week_qty+cum_qty
Expected output:
+--------+---------+-------+-----+---------------+---------+
| row_no | Product | value | qoh | prev_week_qty | cum_qty |
+--------+---------+-------+-----+---------------+---------+
| 1 | pr:1 | 101 | 101 | NULL | NULL |
| 2 | pr:1 | 201 | 101 | NULL | 100 |
| 3 | pr:1 | 201 | 101 | NULL | NULL |
| 4 | pr:1 | 201 | 101 | NULL | NULL |
| 5 | pr:1 | 183 | 101 | NULL | -18 |
| 6 | pr:1 | 183 | 101 | NULL | NULL |
| 7 | pr:1 | 183 | 101 | NULL | NULL |
| 8 | pr:1 | 149 | 101 | NULL | -34 |
| 9 | pr:1 | 131 | 101 | NULL | -18 |
| 10 | pr:1 | 131 | 101 | NULL | NULL |
| 11 | pr:1 | 113 | 101 | NULL | -18 |
| 12 | pr:1 | 113 | 101 | NULL | NUll |
| 13 | pr:1 | 113 | 101 | NULL | NUll |
| 14 | pr:1 | 113 | 101 | NULL | NUll |
| 17 | pr:1 | 101 | 101 | NULL | NULL |
+--------+---------+-------+-----+---------------+---------+
I am using SQL Server 2008 R2.
In SQL SERVER 2012+ you can use SUM()OVER(ORDER BY) trick unfortunately you are using older version. Try something like this
SELECT *
FROM Yourtable A
CROSS apply (SELECT Sum(Isnull([cum_qty], 0)
+ Isnull(prev_week_qty, 0) + CASE WHEN row_no = 1 THEN qoh ELSE 0 END) su
FROM Yourtable B
WHERE a.[row_no] >= b.[row_no]) cs

How to retrieve the data on a single row?

I have a table with some data, something like this:
+---------+---------+---------+---------+-------------+
| Column1 | Column2 | Column3 | Column4 | Column5 |
+---------+---------+---------+---------+-------------+
| 38073 | 16 | abc | 444 | 4/28/2015 |
| 38076 | 70 | gug | 555 | 4/30/2015 |
| 38098 | 13 | yyy | 111 | 5/12/2015 |
| 38098 | 13 | yyy | 112 | 5/13/2015 |
| 38098 | 13 | yyy | 113 | 5/14/2015 |
| 38098 | 13 | yyy | 114 | 5/15/2015 |
| 38100 | 17 | abc | 115 | 5/13/2015 |
+---------+---------+---------+---------+-------------+
What I want to do is to have the values from Columns 4 and 5 on a single row, something like this :
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
| Col1 | Col4Val1 | Col5Val1 | Col4Val2 | Col5Val2 | Col4Val3 | Col5Val3 | Col4Val4 | Col5Val4 |
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
| 38073 | 444 | 4/28/2015 | null | null | null | null | null | null |
| 38076 | 555 | 4/30/2015 | null | null | null | null | null | null |
| 38098 | 111 | 5/12/2015 | 112 | 5/13/2015 | 113 | 5/14/2015 | 114 | 5/15/2015 |
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
Appreciate the help if possible.
Thank you.
Bogdan
You can use a UNION to unpivot the data with a CTE, then PIVOT the columns. You can achieve this dynamically too, there are hundreds of articles that will show you how to do that:
;WITH CTE AS (
SELECT [Column1], CAST([Column4] AS VARCHAR) AS [ColumnVals], 'Col4Val'+CAST(ROW_NUMBER() OVER(PARTITION BY [Column1] ORDER BY (SELECT 1)) AS VARCHAR) AS [Pivot]
FROM Table1
UNION
SELECT [Column1], [Column5], 'Col5Val'+CAST(ROW_NUMBER() OVER(PARTITION BY [Column1] ORDER BY (SELECT 1)) AS VARCHAR) AS [Pivot]
FROM Table1)
SELECT [Column1], [Col4Val1], [Col5Val1], [Col4Val2], [Col5Val2], [Col4Val3], [Col5Val3], [Col4Val4], [Col5Val4]
FROM CTE
PIVOT (MAX([ColumnVals]) FOR [Pivot] IN ([Col4Val1], [Col5Val1], [Col4Val2], [Col5Val2], [Col4Val3], [Col5Val3], [Col4Val4], [Col5Val4])) PIV
Here's a working fiddle: http://sqlfiddle.com/#!6/e992f/1

Resources