Sum in subquery for a group of numbers - sql-server

We are trying to get a combined table where we also try to sum the volume.
Dateset right now:
+-------------+-----+------------+------------+--------+---------+
| Voorziening | BSN | Begindatum | Einddatum | Volume | Product |
+-------------+-----+------------+------------+--------+---------+
| 1000 | 1 | 1-1-2017 | 31-1-2017 | 50 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1200 | 1 | 1-2-2017 | 31-3-2017 | 200 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1250 | 1 | 1-4-2017 | 10-4-2017 | 90 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1111 | 2 | 4-1-2017 | 10-1-2017 | 4 | AABB |
+-------------+-----+------------+------------+--------+---------+
| 1345 | 2 | 11-1-2017 | 29-1-2017 | 80 | AABB |
+-------------+-----+------------+------------+--------+---------+
| 2000 | 1 | 10-1-2017 | 31-1-2017 | 90 | CCCC |
+-------------+-----+------------+------------+--------+---------+
| 2190 | 1 | 1-2-2017 | 31-12-2017 | 100 | CCCC |
+-------------+-----+------------+------------+--------+---------+
What I want to achieve
+-------------+-----+------------+------------+--------+---------+
| Voorziening | BSN | Begindatum | Einddatum | Volume | Product |
+-------------+-----+------------+------------+--------+---------+
| 1000 | 1 | 1-1-2017 | 10-4-2017 | 340 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 2000 | 1 | 10-1-2017 | 31-12-2017 | 190 | CCCC |
+-------------+-----+------------+------------+--------+---------+
| 1111 | 2 | 4-1-2017 | 29-1-2017 | 84 | AABB |
+-------------+-----+------------+------------+--------+---------+
What i've got so for is the folowwing query:
SELECT min(b.Voorziening) as voorzieningsnummer
,a.BSN
,min(b.Begindatum) as mindatum
,MAX(b.Einddatum) AS maxdatum
,a.Productcode
,
(SELECT sum(Volume)
FROM Voorziening
)as totaal
FROM Voorziening a
INNER JOIN Voorziening b
ON a.BSN = b.BSN
AND a.Productcode = b.Productcode
GROUP BY a.BSN, a.Productcode
The result is gives me is this:
+-------------+-----+------------+------------+--------+
| Voorziening | BSN | Begindatum | Einddatum | Volume |
+-------------+-----+------------+------------+--------+
| 1000 | 1 | 1-1-2017 | 10-4-2017 | 424 |
+-------------+-----+------------+------------+--------+
| 1111 | 2 | 4-1-2017 | 29-1-2017 | 424 |
+-------------+-----+------------+------------+--------+
You guys can help me to get the sum right?

There isn't any reason to use JOIN. you can use aggregate function directly.
You can try this.
SELECT min(a.Voorziening) as voorzieningsnummer
,a.BSN
,min(a.Begindatum) as mindatum
,MAX(a.Einddatum) AS maxdatum
,a.Productcode
,SUM(a.Volume) Volume
FROM Voorziening a
GROUP BY a.BSN, a.Productcode

if you are using sql server 2008 or above version then just go ahead with PARTITION BY
SUM(Volume)over(Partition by Product order by Voorziening,another,another)

Related

Sum, Group by and Null

I'm dipping my toes into SQL. I have the following table
+------+----+------+------+-------+
| Type | ID | QTY | Rate | Name |
+------+----+------+------+-------+
| B | 1 | 1000 | 21 | Jack |
| B | 2 | 2000 | 12 | Kevin |
| B | 1 | 3000 | 24 | Jack |
| B | 1 | 1000 | 23 | Jack |
| B | 3 | 200 | 13 | Mary |
| B | 2 | 3000 | 12 | Kevin |
| B | 4 | 4000 | 44 | Chris |
| B | 4 | 5000 | 43 | Chris |
| B | 3 | 1000 | 26 | Mary |
+------+----+------+------+-------+
I don't know how I would leverage Sum and Group by to achieve the following result.
+------+----+------+------+-------+------------+
| Type | ID | QTY | Rate | Name | Sum of QTY |
+------+----+------+------+-------+------------+
| B | 1 | 1000 | 21 | Jack | 5000 |
| B | 1 | 3000 | 24 | Jack | Null |
| B | 1 | 1000 | 23 | Jack | Null |
| B | 2 | 3000 | 12 | Kevin | 5000 |
| B | 2 | 3000 | 12 | Kevin | Null |
| B | 3 | 200 | 13 | Mary | 1200 |
| B | 3 | 1000 | 26 | Mary | Null |
| B | 4 | 4000 | 44 | Chris | 9000 |
| B | 4 | 5000 | 43 | Chris | Null |
+------+----+------+------+-------+------------+
Any help is appreciated!
You can use window function :
select t.*,
(case when row_number() over (partition by type, id order by name) = 1
then sum(qty) over (partition by type, id order by name)
end) as Sum_of_QTY
from table t;

Unpivoting multiple, repeated columns with multiple (denormalized) values

I have a table with multiple columns like this...
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| Name | Email | Address | Order1 | Shipping1 | Date1 | Order2 | Shipping2 | Date2 | Order3 | Shipping3 | Date3 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 | Computer | 123 | 07/11/2017 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 | Laptop | 234 | 08/11/2017 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 | Mouse | 345 | 09/11/2017 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 | Screen | 456 | 10/11/2017 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 | Pen Drive | 678 | 11/11/2017 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
And I want to unpivot the columns into rows like this in T-SQL...
+-------+----------------+---------+-----------+----------+------------+
| Name | Email | Address | Order | Shipping | Date |
+-------+----------------+---------+-----------+----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 |
| John | john#abcd.com | 123 | Computer | 123 | 07/11/2017 |
| John | john#abcd.com | 123 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 |
| Jane | jane#abcd.com | 234 | Laptop | 234 | 08/11/2017 |
| Jane | jane#abcd.com | 234 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 |
| Julie | julie#abcd.com | 345 | Mouse | 345 | 09/11/2017 |
| Julie | julie#abcd.com | 345 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 |
| Jaden | jaden#abcd.com | 456 | Screen | 456 | 10/11/2017 |
| Jaden | jaden#abcd.com | 456 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 |
| Jabba | jabba#abcd.com | 678 | Pen Drive | 678 | 11/11/2017 |
| Jabba | jabba#abcd.com | 678 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+-----------+----------+------------+
I googled and checked other posts related to this but unable to get three values. :(
Appreciate the help!
You won't need to necessarily use UNPIVOT here at all.
You'll be able to UNION the three denormalized Orders back into a flattened output, like so:
SELECT name, Email, Address, Order1 AS Order, Shipping1 as Shipping, Date1 AS Date
FROM Table1
UNION ALL
SELECT name, Email, Address, Order2, Shipping2, Date2
FROM Table1
UNION ALL
SELECT name, Email, Address, Order3, Shipping3, Date3
FROM Table1
ORDER BY Name, Date;
SqlFiddle here
(The column names are set by the first select in the UNION, and the ORDER is applied to the final UNIONed data)

SQL Server : How to subtract values throughout the rows by using values in another column?

I have a table named stock and sales as below :
Stock Table :
+--------+----------+---------+
| Stk_ID | Stk_Name | Stk_Qty |
+--------+----------+---------+
| 1001 | A | 20 |
| 1002 | B | 50 |
+--------+----------+---------+
Sales Table :
+----------+------------+------------+-----------+
| Sales_ID | Sales_Date | Sales_Item | Sales_Qty |
+----------+------------+------------+-----------+
| 2001 | 2016-07-15 | A | 5 |
| 2002 | 2016-07-20 | B | 7 |
| 2003 | 2016-07-23 | A | 4 |
| 2004 | 2016-07-29 | A | 2 |
| 2005 | 2016-08-03 | B | 15 |
| 2006 | 2016-08-07 | B | 10 |
| 2007 | 2016-08-10 | A | 5 |
+----------+------------+------------+-----------+
With the table above, how can I find the available stock Ava_Stk for each stock after every sales?
Ava_Stk is expected to subtract Sales_Qty from Stk_Qty after every sales.
+----------+------------+------------+-----------+---------+
| Sales_ID | Sales_Date | Sales_Item | Sales_Qty | Ava_Stk |
+----------+------------+------------+-----------+---------+
| 2001 | 2016-07-15 | A | 5 | 15 |
| 2002 | 2016-07-20 | B | 7 | 43 |
| 2003 | 2016-07-23 | A | 4 | 11 |
| 2004 | 2016-07-29 | A | 2 | 9 |
| 2005 | 2016-08-03 | B | 15 | 28 |
| 2006 | 2016-08-07 | B | 10 | 18 |
| 2007 | 2016-08-10 | A | 5 | 4 |
+----------+------------+------------+-----------+---------+
Thank you!
You want a cumulative sum and to subtract it from the stock table. In SQL Server 2012+:
select s.*,
(st.stk_qty -
sum(s.sales_qty) over (partition by s.sales_item order by sales_date)
) as ava_stk
from sales s join
stock st
on s.sales_item = st.stk_name;

Values differences between days

I have a SQL Server 2005 table titled "Journeys" as follows:
+---------------+
| Journeys |
+---------------+
| JourneyID |
| PlateNumber |
| DepartureDate |
| DepartureKM |
| ArrivalDate |
| ArrivalKM |
+---------------+
The table contains the following sample data:
+------------+--------------+----------------+--------------+--------------+-----------+
| JOURNEYID | PLATENUMBER | DEPARTUREDATE | DEPARTUREKM | ARRIVALDATE | ARRIVALKM |
+------------+--------------+----------------+--------------+--------------+-----------+
| 1 | ABC-123 | 01-01-2015 | 10000 | 01-02-2015 | 10200 |
| 2 | ABC-123 | 01-02-2015 | 10210 | 01-03-2015 | 10500 |
| 3 | ABC-123 | 01-03-2015 | 10500 | 01-04-2015 | 10650 |
| 4 | ABC-123 | 01-04-2015 | 10607 | 01-05-2015 | 10900 |
| 5 | XYZ-999 | 01-15-2015 | 30200 | 01-16-2015 | 30400 |
| 6 | XYZ-999 | 01-16-2015 | 30405 | 01-17-2015 | 30600 |
| 7 | XYZ-999 | 01-17-2015 | 30600 | 01-18-2015 | 30750 |
| 8 | XYZ-999 | 01-18-2015 | 30752 | 01-19-2015 | 30920 |
+------------+--------------+----------------+--------------+--------------+-----------+
I want to generate a query that returns a the following results with an extra column named 'KMDifference' which is the difference between 'ArrivalKM' from last day and 'DepartureKM' from today.
Desired results:
+-------------+---------------+-------------+-------------+-----------+--------------+
| PlateNumber | DepartureDate | DepartureKM | ArrivalDate | ArrivalKM | KMDifference |
+-------------+---------------+-------------+-------------+-----------+--------------+
| ABC-123 | 01-01-2015 | 10000 | 01-02-2015 | 10200 | 0 |
| ABC-123 | 01-02-2015 | 10210 | 01-03-2015 | 10500 | 10 |
| ABC-123 | 01-03-2015 | 10500 | 01-04-2015 | 10650 | 0 |
| ABC-123 | 01-04-2015 | 10607 | 01-05-2015 | 10900 | 7 |
| XYZ-999 | 01-15-2015 | 30200 | 01-16-2015 | 30400 | 0 |
| XYZ-999 | 01-16-2015 | 30405 | 01-17-2015 | 30600 | 5 |
| XYZ-999 | 01-17-2015 | 30600 | 01-18-2015 | 30750 | 0 |
| XYZ-999 | 01-18-2015 | 30752 | 01-19-2015 | 30920 | 2 |
+-------------+---------------+-------------+-------------+-----------+--------------+
See this SQL Fiddle here: http://sqlfiddle.com/#!3/28abd
You can use the following CTE based query in order to simulate LAG function available from SQL Server 2012 onwards:
;WITH Journeys_rn AS (
SELECT JourneyID, PlateNumber, DepartureDate, DepartureKM, ArrivalDate, ArrivalKM,
ROW_NUMBER() OVER(PARTITION BY PlateNumber ORDER BY DepartureDate) AS rn
FROM Journeys
)
SELECT j1.PlateNumber, j1.DepartureDate, j1.DepartureKM,
j1.ArrivalDate, j1.ArrivalKM,
j1.DepartureKM - ISNULL(j2.ArrivalKM, j1.DepartureKM) AS KMDifference
FROM Journeys_rn AS j1
LEFT JOIN Journeys_rn AS j2 ON j1.rn = j2.rn+1 AND j1.PlateNumber = j2.PlateNumber
j2.ArrivalKM in the above query is the value from previous record. ISNULL is needed so that a 0 value is calculated for the first record of each group.
SQL Fiddle Demo
P.S. The sample data in the OP do not match with the sample data of the SQL Fiddle source also provided in the OP. So had to fix it in order to get the desired reult set.

Table data into Pivot

An Accounting Table has the sample data shown below:
(There could be more AcctgHeads than those shown here)
+-------+-----------+--------+-----+
| Loan | AcctgHead | Amount | D_C |
+-------+-----------+--------+-----+
| 1 | Principal | 10000 | D |
| 1 | Principal | 500 | C |
| 1 | Cash | 10000 | C |
| 1 | Cash | 500 | D |
| 2 | Principal | 5000 | D |
| 2 | Cash | 5000 | C |
| 2 | Cash | 300 | D |
| 2 | Principal | 300 | C |
| 1 | IntDue | 50 | D |
| 1 | IntIncome | 50 | C |
+-------+-----------+--------+-----+
The desired ouput is:
+------+-------------+-------------+--------+--------+----------+----------+-------------+-------------+
| Loan | Principal_D | Principal_C | Cash_D | Cash_C | IntDue_D | IntDue_C | IntIncome_D | IntIncome_C |
+------+-------------+-------------+--------+--------+----------+----------+-------------+-------------+
| 1 | 10000 | 500 | 500 | 10000 | 50 | 0 | 0 | 50 |
| 2 | 5000 | 300 | 300 | 5000 | 0 | 0 | 0 | 0 |
+------+-------------+-------------+--------+--------+----------+----------+-------------+-------------+
What would be the query to accomplish this?
Thanks in advance for the help.
Try this: (assuming your acctghead has fixed number of values as shown)
select loan,
isnull(Principal_D,0) Principal_D,
isnull(Principal_C,0) Principal_C,
isnull(Cash_D,0) Cash_D,
isnull(Cash_C,0) Cash_C,
isnull(IntDue_D,0) IntDue_D,
isnull(IntDue_C,0) IntDue_C,
isnull(IntIncome_D,0) IntIncome_D,
isnull(IntIncome_C,0) IntIncome_C
from
(select loan, amount, AcctgHead + '_' + D_C As AcctgHeadDC from t) t
pivot
(
max(amount) for AcctgHeadDC in
(Principal_D,Principal_C,Cash_D,Cash_C,
IntDue_D,IntDue_C,IntIncome_D,IntIncome_C)
) p
SQL DEMO

Resources